Merge "Mark RotationLayer as trusted for untrusted touches"
diff --git a/Android.bp b/Android.bp
index ff62106..5c0dd63 100644
--- a/Android.bp
+++ b/Android.bp
@@ -223,6 +223,9 @@
"media/java/**/*.java",
"media/java/**/*.aidl",
],
+ exclude_srcs: [
+ ":framework-media-tv-tunerresourcemanager-sources-aidl",
+ ],
path: "media/java",
}
@@ -529,6 +532,7 @@
"android.hardware.vibrator-V1.2-java",
"android.hardware.vibrator-V1.3-java",
"android.security.apc-java",
+ "android.security.authorization-java",
"android.system.keystore2-java",
"android.system.suspend.control.internal-java",
"cameraprotosnano",
@@ -630,6 +634,7 @@
// in favor of an API stubs dependency in java_library "framework" below.
"mimemap",
"av-types-aidl-java",
+ "tv_tuner_resource_manager_aidl_interface-java",
"soundtrigger_middleware-aidl-java",
"modules-utils-os",
],
diff --git a/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java b/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java
index a320514..1bb98cb 100644
--- a/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/PendingIntentPerfTest.java
@@ -62,7 +62,7 @@
state.resumeTiming();
final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, mIntent,
- 0);
+ PendingIntent.FLAG_MUTABLE_UNAUDITED);
state.pauseTiming();
pendingIntent.cancel();
@@ -80,11 +80,11 @@
while (state.keepRunning()) {
state.pauseTiming();
final PendingIntent previousPendingIntent = PendingIntent.getActivity(mContext, 0,
- mIntent, 0);
+ mIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
state.resumeTiming();
final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, mIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
state.pauseTiming();
pendingIntent.cancel();
@@ -102,11 +102,11 @@
while (state.keepRunning()) {
state.pauseTiming();
final PendingIntent previousPendingIntent = PendingIntent.getActivity(mContext, 0,
- mIntent, 0);
+ mIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
state.resumeTiming();
final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, mIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
state.pauseTiming();
previousPendingIntent.cancel();
@@ -124,7 +124,7 @@
while (state.keepRunning()) {
state.pauseTiming();
final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
- mIntent, 0);
+ mIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
state.resumeTiming();
pendingIntent.cancel();
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java b/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
index a433d80..530dc9d 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/TestPackageInstaller.java
@@ -134,7 +134,7 @@
Intent intent = new Intent(action);
PendingIntent pending = PendingIntent.getBroadcast(mContext, sessionId, intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
return pending.getIntentSender();
}
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
index ae32fba..2320b75 100644
--- a/apex/appsearch/framework/api/current.txt
+++ b/apex/appsearch/framework/api/current.txt
@@ -8,6 +8,7 @@
}
public class AppSearchManager {
+ method public void createGlobalSearchSession(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.GlobalSearchSession>>);
method public void createSearchSession(@NonNull android.app.appsearch.AppSearchManager.SearchContext, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.AppSearchSession>>);
}
@@ -80,7 +81,8 @@
method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setTokenizerType(int);
}
- public final class AppSearchSession {
+ public final class AppSearchSession implements java.io.Closeable {
+ method public void close();
method public void getByUri(@NonNull android.app.appsearch.GetByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,android.app.appsearch.GenericDocument>);
method public void getSchema(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.Set<android.app.appsearch.AppSearchSchema>>>);
method public void putDocuments(@NonNull android.app.appsearch.PutDocumentsRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
@@ -149,6 +151,11 @@
method @NonNull public android.app.appsearch.GetByUriRequest.Builder setNamespace(@NonNull String);
}
+ public class GlobalSearchSession implements java.io.Closeable {
+ method public void close();
+ method @NonNull public android.app.appsearch.SearchResults query(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor);
+ }
+
public class PackageIdentifier {
ctor public PackageIdentifier(@NonNull String, @NonNull byte[]);
method @NonNull public String getPackageName();
@@ -162,7 +169,7 @@
public static final class PutDocumentsRequest.Builder {
ctor public PutDocumentsRequest.Builder();
method @NonNull public android.app.appsearch.PutDocumentsRequest.Builder addGenericDocument(@NonNull android.app.appsearch.GenericDocument...);
- method @NonNull public android.app.appsearch.PutDocumentsRequest.Builder addGenericDocument(@NonNull java.util.Collection<android.app.appsearch.GenericDocument>);
+ method @NonNull public android.app.appsearch.PutDocumentsRequest.Builder addGenericDocument(@NonNull java.util.Collection<? extends android.app.appsearch.GenericDocument>);
method @NonNull public android.app.appsearch.PutDocumentsRequest build();
}
@@ -182,6 +189,7 @@
public final class SearchResult {
method @NonNull public android.app.appsearch.GenericDocument getDocument();
method @NonNull public java.util.List<android.app.appsearch.SearchResult.MatchInfo> getMatches();
+ method @NonNull public String getPackageName();
}
public static final class SearchResult.MatchInfo {
@@ -204,9 +212,11 @@
}
public final class SearchSpec {
+ method @NonNull public java.util.List<java.lang.String> getFilterPackageNames();
method public int getMaxSnippetSize();
method @NonNull public java.util.List<java.lang.String> getNamespaces();
method public int getOrder();
+ method @NonNull public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getProjections();
method public int getRankingStrategy();
method public int getResultCountPerPage();
method @NonNull public java.util.List<java.lang.String> getSchemaTypes();
@@ -215,17 +225,23 @@
method public int getTermMatch();
field public static final int ORDER_ASCENDING = 1; // 0x1
field public static final int ORDER_DESCENDING = 0; // 0x0
+ field public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*";
field public static final int RANKING_STRATEGY_CREATION_TIMESTAMP = 2; // 0x2
field public static final int RANKING_STRATEGY_DOCUMENT_SCORE = 1; // 0x1
field public static final int RANKING_STRATEGY_NONE = 0; // 0x0
+ field public static final int RANKING_STRATEGY_RELEVANCE_SCORE = 3; // 0x3
field public static final int TERM_MATCH_EXACT_ONLY = 1; // 0x1
field public static final int TERM_MATCH_PREFIX = 2; // 0x2
}
public static final class SearchSpec.Builder {
ctor public SearchSpec.Builder();
+ method @NonNull public android.app.appsearch.SearchSpec.Builder addFilterPackageNames(@NonNull java.lang.String...);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder addFilterPackageNames(@NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.SearchSpec.Builder addNamespace(@NonNull java.lang.String...);
method @NonNull public android.app.appsearch.SearchSpec.Builder addNamespace(@NonNull java.util.Collection<java.lang.String>);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder addProjection(@NonNull String, @NonNull java.lang.String...);
+ method @NonNull public android.app.appsearch.SearchSpec.Builder addProjection(@NonNull String, @NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.SearchSpec.Builder addSchemaType(@NonNull java.lang.String...);
method @NonNull public android.app.appsearch.SearchSpec.Builder addSchemaType(@NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.SearchSpec build();
diff --git a/apex/appsearch/framework/api/system-current.txt b/apex/appsearch/framework/api/system-current.txt
index 73a4a19..4a6194e 100644
--- a/apex/appsearch/framework/api/system-current.txt
+++ b/apex/appsearch/framework/api/system-current.txt
@@ -1,17 +1,9 @@
// Signature format: 2.0
package android.app.appsearch {
- public class AppSearchManager {
- method public void createGlobalSearchSession(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.GlobalSearchSession>>);
- }
-
public class AppSearchManagerFrameworkInitializer {
method public static void initialize();
}
- public class GlobalSearchSession {
- method @NonNull public android.app.appsearch.SearchResults query(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor);
- }
-
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index 685e5ff..6fa8f85 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -17,7 +17,6 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.Bundle;
@@ -28,6 +27,7 @@
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -122,8 +122,8 @@
/**
* Creates a new {@link AppSearchSession}.
*
- * <p>This process requires an AppSearch native indexing file system for each user. If it's not
- * created for this user, the initialization process will create one under user's directory.
+ * <p>This process requires an AppSearch native indexing file system. If it's not created, the
+ * initialization process will create one under the user's credential encrypted directory.
*
* @param searchContext The {@link SearchContext} contains all information to create a new
* {@link AppSearchSession}
@@ -146,16 +146,14 @@
/**
* Creates a new {@link GlobalSearchSession}.
*
- * <p>This process requires an AppSearch native indexing file system for each user. If it's not
- * created for this user, the initialization process will create one under user's directory.
+ * <p>This process requires an AppSearch native indexing file system. If it's not created, the
+ * initialization process will create one under the user's credential encrypted directory.
*
* @param executor Executor on which to invoke the callback.
* @param callback The {@link AppSearchResult}<{@link GlobalSearchSession}> of
* performing this operation. Or a {@link AppSearchResult} with failure
* reason code and error information.
- * @hide
*/
- @SystemApi
public void createGlobalSearchSession(
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
@@ -234,6 +232,7 @@
DEFAULT_DATABASE_NAME,
schemaBundles,
new ArrayList<>(request.getSchemasNotVisibleToSystemUi()),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
request.isForceOverride(),
mContext.getUserId(),
new IAppSearchResultCallback.Stub() {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index d628fb5..0427577 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -22,11 +22,13 @@
import android.os.Bundle;
import android.os.ParcelableException;
import android.os.RemoteException;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import com.android.internal.util.Preconditions;
+import java.io.Closeable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -41,7 +43,7 @@
*
* This class is thread safe.
*/
-public final class AppSearchSession {
+public final class AppSearchSession implements Closeable {
private static final String TAG = "AppSearchSession";
private final String mDatabaseName;
@UserIdInt
@@ -161,11 +163,22 @@
for (AppSearchSchema schema : request.getSchemas()) {
schemaBundles.add(schema.getBundle());
}
+ Map<String, List<Bundle>> schemasPackageAccessibleBundles =
+ new ArrayMap<>(request.getSchemasVisibleToPackagesInternal().size());
+ for (Map.Entry<String, Set<PackageIdentifier>> entry :
+ request.getSchemasVisibleToPackagesInternal().entrySet()) {
+ List<Bundle> packageIdentifierBundles = new ArrayList<>(entry.getValue().size());
+ for (PackageIdentifier packageIdentifier : entry.getValue()) {
+ packageIdentifierBundles.add(packageIdentifier.getBundle());
+ }
+ schemasPackageAccessibleBundles.put(entry.getKey(), packageIdentifierBundles);
+ }
try {
mService.setSchema(
mDatabaseName,
schemaBundles,
new ArrayList<>(request.getSchemasNotVisibleToSystemUi()),
+ schemasPackageAccessibleBundles,
request.isForceOverride(),
mUserId,
new IAppSearchResultCallback.Stub() {
@@ -478,11 +491,10 @@
}
/**
- * Closes the SearchSessionImpl to persists all update/delete requests to the disk.
- *
- * @hide
+ * Closes the {@link AppSearchSession} to persist all schema and document updates, additions,
+ * and deletes to disk.
*/
- // TODO(b/175637134) when unhide it, implement Closeable and remove this method.
+ @Override
public void close() {
if (mIsMutated && !mIsClosed) {
try {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
index 95f7d79..e4e030e 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
@@ -19,10 +19,12 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.os.RemoteException;
+import com.android.internal.util.Preconditions;
+
+import java.io.Closeable;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -31,14 +33,13 @@
* This class provides global access to the centralized AppSearch index maintained by the system.
*
* <p>Apps can retrieve indexed documents through the query API.
- * @hide
*/
-@SystemApi
-public class GlobalSearchSession {
+public class GlobalSearchSession implements Closeable {
private final IAppSearchManager mService;
@UserIdInt
private final int mUserId;
+ private boolean mIsClosed = false;
static void createGlobalSearchSession(
@NonNull IAppSearchManager service,
@@ -129,7 +130,14 @@
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpec);
Objects.requireNonNull(executor);
+ Preconditions.checkState(!mIsClosed, "GlobalSearchSession has already been closed");
return new SearchResults(mService, /*databaseName=*/null, queryExpression,
searchSpec, mUserId, executor);
}
+
+ /** Closes the {@link GlobalSearchSession}. */
+ @Override
+ public void close() {
+ mIsClosed = true;
+ }
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index af8b613..2b43777 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -34,6 +34,8 @@
* @param schemaBundles List of {@link AppSearchSchema} bundles.
* @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
* surfaces.
+ * @param schemasPackageAccessibleBundles Schema types that are visible to the specified
+ * packages. The value List contains PackageIdentifier Bundles.
* @param forceOverride Whether to apply the new schema even if it is incompatible. All
* incompatible documents will be deleted.
* @param userId Id of the calling user
@@ -44,11 +46,11 @@
in String databaseName,
in List<Bundle> schemaBundles,
in List<String> schemasNotPlatformSurfaceable,
+ in Map<String, List<Bundle>> schemasPackageAccessibleBundles,
boolean forceOverride,
in int userId,
in IAppSearchResultCallback callback);
-
/**
* Retrieves the AppSearch schema for this database.
*
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java b/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java
index 43be442..bfb9323 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java
@@ -17,16 +17,17 @@
package android.app.appsearch;
import android.annotation.NonNull;
+import android.app.appsearch.util.BundleUtil;
+import android.os.Bundle;
import com.android.internal.util.Preconditions;
-import java.util.Arrays;
-import java.util.Objects;
-
/** This class represents a uniquely identifiable package. */
public class PackageIdentifier {
- private final String mPackageName;
- private final byte[] mSha256Certificate;
+ private static final String PACKAGE_NAME_FIELD = "packageName";
+ private static final String SHA256_CERTIFICATE_FIELD = "sha256Certificate";
+
+ private final Bundle mBundle;
/**
* Creates a unique identifier for a package.
@@ -35,18 +36,30 @@
* @param sha256Certificate SHA256 certificate digest of the package.
*/
public PackageIdentifier(@NonNull String packageName, @NonNull byte[] sha256Certificate) {
- mPackageName = Preconditions.checkNotNull(packageName);
- mSha256Certificate = Preconditions.checkNotNull(sha256Certificate);
+ mBundle = new Bundle();
+ mBundle.putString(PACKAGE_NAME_FIELD, packageName);
+ mBundle.putByteArray(SHA256_CERTIFICATE_FIELD, sha256Certificate);
+ }
+
+ /** @hide */
+ public PackageIdentifier(@NonNull Bundle bundle) {
+ mBundle = Preconditions.checkNotNull(bundle);
+ }
+
+ /** @hide */
+ @NonNull
+ public Bundle getBundle() {
+ return mBundle;
}
@NonNull
public String getPackageName() {
- return mPackageName;
+ return Preconditions.checkNotNull(mBundle.getString(PACKAGE_NAME_FIELD));
}
@NonNull
public byte[] getSha256Certificate() {
- return mSha256Certificate;
+ return Preconditions.checkNotNull(mBundle.getByteArray(SHA256_CERTIFICATE_FIELD));
}
@Override
@@ -58,12 +71,11 @@
return false;
}
final PackageIdentifier other = (PackageIdentifier) obj;
- return this.mPackageName.equals(other.mPackageName)
- && Arrays.equals(this.mSha256Certificate, other.mSha256Certificate);
+ return BundleUtil.deepEquals(mBundle, other.mBundle);
}
@Override
public int hashCode() {
- return Objects.hash(mPackageName, Arrays.hashCode(mSha256Certificate));
+ return BundleUtil.deepHashCode(mBundle);
}
}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
index b9503ee..0f141d6 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
@@ -30,7 +30,7 @@
/**
* Encapsulates a request to index a document into an {@link AppSearchSession} database.
*
- * @see AppSearchSession#putDocuments
+ * <p>@see AppSearchSession#putDocuments
*/
public final class PutDocumentsRequest {
private final List<GenericDocument> mDocuments;
@@ -45,12 +45,16 @@
return Collections.unmodifiableList(mDocuments);
}
- /** Builder for {@link PutDocumentsRequest} objects. */
+ /**
+ * Builder for {@link PutDocumentsRequest} objects.
+ *
+ * <p>Once {@link #build} is called, the instance can no longer be used.
+ */
public static final class Builder {
private final List<GenericDocument> mDocuments = new ArrayList<>();
private boolean mBuilt = false;
- /** Adds one or more documents to the request. */
+ /** Adds one or more {@link GenericDocument} objects to the request. */
@SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
@NonNull
public Builder addGenericDocument(@NonNull GenericDocument... documents) {
@@ -58,17 +62,18 @@
return addGenericDocument(Arrays.asList(documents));
}
- /** Adds one or more documents to the request. */
+ /** Adds a collection of {@link GenericDocument} objects to the request. */
@SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
@NonNull
- public Builder addGenericDocument(@NonNull Collection<GenericDocument> documents) {
+ public Builder addGenericDocument(
+ @NonNull Collection<? extends GenericDocument> documents) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(documents);
mDocuments.addAll(documents);
return this;
}
- /** Builds a new {@link PutDocumentsRequest}. */
+ /** Creates a new {@link PutDocumentsRequest} object. */
@NonNull
public PutDocumentsRequest build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
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 eb0b7324..4931cc0 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SearchResult.java
@@ -109,10 +109,9 @@
}
/**
- * Contains the package name that stored the {@link GenericDocument}.
+ * Contains the package name of the app that stored the {@link GenericDocument}.
*
* @return Package name that stored the document
- * @hide
*/
@NonNull
public String getPackageName() {
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 c3f0d8a..b5d5f04d 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.IllegalSearchSpecException;
import android.os.Bundle;
import android.util.ArrayMap;
@@ -42,17 +43,15 @@
// TODO(sidchhabra) : AddResultSpec fields for Snippets etc.
public final class SearchSpec {
/**
- * Schema type to be used in {@link SearchSpec.Builder#addProjectionTypePropertyPath} to apply
- * property paths to all results, excepting any types that have had their own, specific property
- * paths set.
- *
- * @hide
+ * Schema type to be used in {@link SearchSpec.Builder#addProjection} to apply property paths to
+ * all results, excepting any types that have had their own, specific property paths set.
*/
public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*";
static final String TERM_MATCH_TYPE_FIELD = "termMatchType";
static final String SCHEMA_TYPE_FIELD = "schemaType";
static final String NAMESPACE_FIELD = "namespace";
+ static final String PACKAGE_NAME_FIELD = "packageName";
static final String NUM_PER_PAGE_FIELD = "numPerPage";
static final String RANKING_STRATEGY_FIELD = "rankingStrategy";
static final String ORDER_FIELD = "order";
@@ -106,7 +105,8 @@
value = {
RANKING_STRATEGY_NONE,
RANKING_STRATEGY_DOCUMENT_SCORE,
- RANKING_STRATEGY_CREATION_TIMESTAMP
+ RANKING_STRATEGY_CREATION_TIMESTAMP,
+ RANKING_STRATEGY_RELEVANCE_SCORE
})
@Retention(RetentionPolicy.SOURCE)
public @interface RankingStrategy {}
@@ -117,6 +117,8 @@
public static final int RANKING_STRATEGY_DOCUMENT_SCORE = 1;
/** Ranked by document creation timestamps. */
public static final int RANKING_STRATEGY_CREATION_TIMESTAMP = 2;
+ /** Ranked by document relevance score. */
+ public static final int RANKING_STRATEGY_RELEVANCE_SCORE = 3;
/**
* Order for query result.
@@ -172,7 +174,7 @@
}
/**
- * Returns the list of namespaces to search for.
+ * Returns the list of namespaces to search over.
*
* <p>If empty, the query will search over all namespaces.
*/
@@ -185,6 +187,40 @@
return Collections.unmodifiableList(namespaces);
}
+ /**
+ * Returns the list of package name filters to search over.
+ *
+ * <p>If empty, the query will search over all packages that the caller has access to. If
+ * package names are specified which caller doesn't have access to, then those package names
+ * will be ignored.
+ */
+ @NonNull
+ public List<String> getFilterPackageNames() {
+ List<String> packageNames = mBundle.getStringArrayList(PACKAGE_NAME_FIELD);
+ if (packageNames == null) {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableList(packageNames);
+ }
+
+ /**
+ * Returns the list of package names to search over.
+ *
+ * <p>If unset, the query will search over all packages that the caller has access to. If
+ * package names are specified which caller doesn't have access to, then those package names
+ * will be ignored.
+ *
+ * @hide
+ */
+ @NonNull
+ public List<String> getPackageNames() {
+ List<String> packageNames = mBundle.getStringArrayList(PACKAGE_NAME_FIELD);
+ if (packageNames == null) {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableList(packageNames);
+ }
+
/** Returns the number of results per page in the result set. */
public int getResultCountPerPage() {
return mBundle.getInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE);
@@ -224,11 +260,9 @@
*
* <p>Calling this function repeatedly is inefficient. Prefer to retain the Map returned by this
* function, rather than calling it multiple times.
- *
- * @hide
*/
@NonNull
- public Map<String, List<String>> getProjectionTypePropertyPaths() {
+ public Map<String, List<String>> getProjections() {
Bundle typePropertyPathsBundle = mBundle.getBundle(PROJECTION_TYPE_PROPERTY_PATHS_FIELD);
Set<String> schemaTypes = typePropertyPathsBundle.keySet();
Map<String, List<String>> typePropertyPathsMap = new ArrayMap<>(schemaTypes.size());
@@ -245,6 +279,7 @@
private final Bundle mBundle;
private final ArrayList<String> mSchemaTypes = new ArrayList<>();
private final ArrayList<String> mNamespaces = new ArrayList<>();
+ private final ArrayList<String> mPackageNames = new ArrayList<>();
private final Bundle mProjectionTypePropertyMasks = new Bundle();
private boolean mBuilt = false;
@@ -319,6 +354,43 @@
}
/**
+ * Adds a package name filter to {@link SearchSpec} Entry. Only search for documents that
+ * were indexed from the specified packages.
+ *
+ * <p>If unset, the query will search over all packages that the caller has access to. If
+ * package names are specified which caller doesn't have access to, then those package names
+ * will be ignored.
+ */
+ // Getter is called "getFilterPackageNames" (as opposed to the suggested
+ // "getFilterPackageNameses")
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ public Builder addFilterPackageNames(@NonNull String... packageNames) {
+ Preconditions.checkNotNull(packageNames);
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ return addFilterPackageNames(Arrays.asList(packageNames));
+ }
+
+ /**
+ * Adds a package name filter to {@link SearchSpec} Entry. Only search for documents that
+ * were indexed from the specified packages.
+ *
+ * <p>If unset, the query will search over all packages that the caller has access to. If
+ * package names are specified which caller doesn't have access to, then those package names
+ * will be ignored.
+ */
+ // Getter is called "getFilterPackageNames" (as opposed to the suggested
+ // "getFilterPackageNameses")
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ public Builder addFilterPackageNames(@NonNull Collection<String> packageNames) {
+ Preconditions.checkNotNull(packageNames);
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ mPackageNames.addAll(packageNames);
+ return this;
+ }
+
+ /**
* Sets the number of results per page in the returned object.
*
* <p>The default number of results per page is 10.
@@ -339,7 +411,7 @@
Preconditions.checkArgumentInRange(
rankingStrategy,
RANKING_STRATEGY_NONE,
- RANKING_STRATEGY_CREATION_TIMESTAMP,
+ RANKING_STRATEGY_RELEVANCE_SCORE,
"Result ranking strategy");
mBundle.putInt(RANKING_STRATEGY_FIELD, rankingStrategy);
return this;
@@ -480,14 +552,12 @@
* subject: "IMPORTANT"
* }
* }</pre>
- *
- * @hide
*/
@NonNull
- public SearchSpec.Builder addProjectionTypePropertyPaths(
+ public SearchSpec.Builder addProjection(
@NonNull String schemaType, @NonNull String... propertyPaths) {
Preconditions.checkNotNull(propertyPaths);
- return addProjectionTypePropertyPaths(schemaType, Arrays.asList(propertyPaths));
+ return addProjection(schemaType, Arrays.asList(propertyPaths));
}
/**
@@ -503,12 +573,10 @@
* then those property paths will apply to all results, excepting any types that have their
* own, specific property paths set.
*
- * <p>{@see SearchSpec.Builder#addProjectionTypePropertyPath(String, String...)}
- *
- * @hide
+ * <p>{@see SearchSpec.Builder#addProjection(String, String...)}
*/
@NonNull
- public SearchSpec.Builder addProjectionTypePropertyPaths(
+ public SearchSpec.Builder addProjection(
@NonNull String schemaType, @NonNull Collection<String> propertyPaths) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(schemaType);
@@ -535,6 +603,7 @@
}
mBundle.putStringArrayList(NAMESPACE_FIELD, mNamespaces);
mBundle.putStringArrayList(SCHEMA_TYPE_FIELD, mSchemaTypes);
+ mBundle.putStringArrayList(PACKAGE_NAME_FIELD, mPackageNames);
mBundle.putBundle(PROJECTION_TYPE_PROPERTY_PATHS_FIELD, mProjectionTypePropertyMasks);
mBuilt = true;
return new SearchSpec(mBundle);
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 87c41e5..1f1e9a1 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -27,6 +27,7 @@
import android.app.appsearch.IAppSearchBatchResultCallback;
import android.app.appsearch.IAppSearchManager;
import android.app.appsearch.IAppSearchResultCallback;
+import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.content.Context;
@@ -34,6 +35,7 @@
import android.os.Bundle;
import android.os.ParcelableException;
import android.os.RemoteException;
+import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -42,6 +44,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* TODO(b/142567528): add comments when implement this class
@@ -64,6 +67,7 @@
@NonNull String databaseName,
@NonNull List<Bundle> schemaBundles,
@NonNull List<String> schemasNotPlatformSurfaceable,
+ @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
boolean forceOverride,
@UserIdInt int userId,
@NonNull IAppSearchResultCallback callback) {
@@ -78,9 +82,25 @@
for (int i = 0; i < schemaBundles.size(); i++) {
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
}
+ Map<String, List<PackageIdentifier>> schemasPackageAccessible =
+ new ArrayMap<>(schemasPackageAccessibleBundles.size());
+ for (Map.Entry<String, List<Bundle>> entry :
+ schemasPackageAccessibleBundles.entrySet()) {
+ List<PackageIdentifier> packageIdentifiers =
+ new ArrayList<>(entry.getValue().size());
+ for (int i = 0; i < packageIdentifiers.size(); i++) {
+ packageIdentifiers.add(new PackageIdentifier(entry.getValue().get(i)));
+ }
+ schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
+ }
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
String packageName = convertUidToPackageName(callingUid);
- impl.setSchema(packageName, databaseName, schemas, schemasNotPlatformSurfaceable,
+ impl.setSchema(
+ packageName,
+ databaseName,
+ schemas,
+ schemasNotPlatformSurfaceable,
+ schemasPackageAccessible,
forceOverride);
invokeCallbackOnResult(callback,
AppSearchResult.newSuccessfulResult(/*result=*/ null));
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index a2126b1..b754926 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -21,10 +21,12 @@
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
+import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.app.appsearch.exceptions.AppSearchException;
import android.os.Bundle;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -230,6 +232,7 @@
* @param schemas Schemas to set for this app.
* @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
* surfaces.
+ * @param schemasPackageAccessible Schema types that are visible to the specified packages.
* @param forceOverride Whether to force-apply the schema even if it is incompatible. Documents
* which do not comply with the new schema will be deleted.
* @throws AppSearchException on IcingSearchEngine error.
@@ -239,6 +242,7 @@
@NonNull String databaseName,
@NonNull List<AppSearchSchema> schemas,
@NonNull List<String> schemasNotPlatformSurfaceable,
+ @NonNull Map<String, List<PackageIdentifier>> schemasPackageAccessible,
boolean forceOverride)
throws AppSearchException {
mReadWriteLock.writeLock().lock();
@@ -291,7 +295,18 @@
prefixedSchemasNotPlatformSurfaceable.add(
prefix + schemasNotPlatformSurfaceable.get(i));
}
- mVisibilityStoreLocked.setVisibility(prefix, prefixedSchemasNotPlatformSurfaceable);
+
+ Map<String, List<PackageIdentifier>> prefixedSchemasPackageAccessible =
+ new ArrayMap<>(schemasNotPlatformSurfaceable.size());
+ for (Map.Entry<String, List<PackageIdentifier>> entry :
+ schemasPackageAccessible.entrySet()) {
+ prefixedSchemasPackageAccessible.put(prefix + entry.getKey(), entry.getValue());
+ }
+
+ mVisibilityStoreLocked.setVisibility(
+ prefix,
+ prefixedSchemasNotPlatformSurfaceable,
+ prefixedSchemasPackageAccessible);
// Determine whether to schedule an immediate optimize.
if (setSchemaResultProto.getDeletedSchemaTypesCount() > 0
@@ -448,6 +463,13 @@
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec)
throws AppSearchException {
+ if (!searchSpec.getPackageNames().isEmpty()
+ && !searchSpec.getPackageNames().contains(packageName)) {
+ // Client wanted to query over some packages that weren't its own. This isn't
+ // allowed through local query so we can return early with no results.
+ return new SearchResultPage(Bundle.EMPTY);
+ }
+
mReadWriteLock.readLock().lock();
try {
return doQueryLocked(
@@ -480,13 +502,25 @@
// verified.
mReadWriteLock.readLock().lock();
try {
- // We use the mNamespaceMap.keySet here because it's the smaller set of valid prefixes
- // that could exist.
- Set<String> prefixes = mNamespaceMapLocked.keySet();
+ Set<String> prefixes = new ArraySet<>();
+ Set<String> packageFilters = new ArraySet<>(searchSpec.getPackageNames());
- // Filter out any VisibilityStore documents which are AppSearch-internal only.
- prefixes.remove(
- createPrefix(VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME));
+ for (String prefix : mNamespaceMapLocked.keySet()) {
+ if (prefix.equals(VisibilityStore.VISIBILITY_STORE_PREFIX)) {
+ // Filter out any VisibilityStore documents which are AppSearch-internal only.
+ continue;
+ }
+
+ if (!packageFilters.isEmpty() && !packageFilters.contains(getPackageName(prefix))) {
+ // Client wanted to restrict search over specified packages. Since the
+ // specified packages don't include this prefix, don't add it to our search
+ // filters.
+ continue;
+ }
+
+ // Otherwise, include this prefix in our global search.
+ prefixes.add(prefix);
+ }
return doQueryLocked(prefixes, queryExpression, searchSpec);
} finally {
@@ -500,22 +534,30 @@
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec)
throws AppSearchException {
- SearchSpecProto searchSpecProto = SearchSpecToProtoConverter.toSearchSpecProto(searchSpec);
SearchSpecProto.Builder searchSpecBuilder =
- searchSpecProto.toBuilder().setQuery(queryExpression);
-
- ResultSpecProto resultSpec = SearchSpecToProtoConverter.toResultSpecProto(searchSpec);
- ScoringSpecProto scoringSpec = SearchSpecToProtoConverter.toScoringSpecProto(searchSpec);
- SearchResultProto searchResultProto;
-
+ SearchSpecToProtoConverter.toSearchSpecProto(searchSpec).toBuilder()
+ .setQuery(queryExpression);
// rewriteSearchSpecForPrefixesLocked will return false if none of the prefixes that the
// client is trying to search on exist, so we can return an empty SearchResult and skip
// sending request to Icing.
if (!rewriteSearchSpecForPrefixesLocked(searchSpecBuilder, prefixes)) {
return new SearchResultPage(Bundle.EMPTY);
}
- searchResultProto =
- mIcingSearchEngineLocked.search(searchSpecBuilder.build(), scoringSpec, resultSpec);
+
+ ResultSpecProto.Builder resultSpecBuilder =
+ SearchSpecToProtoConverter.toResultSpecProto(searchSpec).toBuilder();
+
+ // rewriteResultSpecForPrefixesLocked will return false if none of the prefixes that the
+ // client is trying to search on exist, so we can return an empty SearchResult and skip
+ // sending request to Icing.
+ if (!rewriteResultSpecForPrefixesLocked(resultSpecBuilder, prefixes)) {
+ return new SearchResultPage(Bundle.EMPTY);
+ }
+
+ ScoringSpecProto scoringSpec = SearchSpecToProtoConverter.toScoringSpecProto(searchSpec);
+ SearchResultProto searchResultProto =
+ mIcingSearchEngineLocked.search(
+ searchSpecBuilder.build(), scoringSpec, resultSpecBuilder.build());
checkSuccess(searchResultProto.getStatus());
return rewriteSearchResultProto(searchResultProto);
@@ -607,6 +649,14 @@
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec)
throws AppSearchException {
+ if (!searchSpec.getPackageNames().isEmpty()
+ && !searchSpec.getPackageNames().contains(packageName)) {
+ // We're only removing documents within the parameter `packageName`. If we're not
+ // restricting our remove-query to this package name, then there's nothing for us to
+ // remove.
+ return;
+ }
+
SearchSpecProto searchSpecProto = SearchSpecToProtoConverter.toSearchSpecProto(searchSpec);
SearchSpecProto.Builder searchSpecBuilder =
searchSpecProto.toBuilder().setQuery(queryExpression);
@@ -915,6 +965,47 @@
return true;
}
+ /**
+ * Rewrites the typePropertyMasks that exist in {@code prefixes}.
+ *
+ * <p>This method should be only called in query methods and get the READ lock to keep thread
+ * safety.
+ *
+ * @return false if none of the requested prefixes exist.
+ */
+ @VisibleForTesting
+ @GuardedBy("mReadWriteLock")
+ boolean rewriteResultSpecForPrefixesLocked(
+ @NonNull ResultSpecProto.Builder resultSpecBuilder, @NonNull Set<String> prefixes) {
+ // Create a copy since retainAll() modifies the original set.
+ Set<String> existingPrefixes = new ArraySet<>(mNamespaceMapLocked.keySet());
+ existingPrefixes.retainAll(prefixes);
+
+ if (existingPrefixes.isEmpty()) {
+ // None of the prefixes exist, empty query.
+ return false;
+ }
+
+ List<ResultSpecProto.TypePropertyMask> prefixedTypePropertyMasks = new ArrayList<>();
+ // Rewrite filters to include a database prefix.
+ for (String prefix : existingPrefixes) {
+ Set<String> existingSchemaTypes = mSchemaMapLocked.get(prefix);
+ // Qualify the given schema types
+ for (ResultSpecProto.TypePropertyMask typePropertyMask :
+ resultSpecBuilder.getTypePropertyMasksList()) {
+ String qualifiedType = prefix + typePropertyMask.getSchemaType();
+ if (existingSchemaTypes.contains(qualifiedType)) {
+ prefixedTypePropertyMasks.add(
+ typePropertyMask.toBuilder().setSchemaType(qualifiedType).build());
+ }
+ }
+ }
+ resultSpecBuilder
+ .clearTypePropertyMasks()
+ .addAllTypePropertyMasks(prefixedTypePropertyMasks);
+ return true;
+ }
+
@VisibleForTesting
@GuardedBy("mReadWriteLock")
SchemaProto getSchemaProtoLocked() throws AppSearchException {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
index 7e4ebb5..a940ec1 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
@@ -20,6 +20,7 @@
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
+import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.exceptions.AppSearchException;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -27,19 +28,21 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.Set;
/**
- * Manages any visibility settings for all the databases that AppSearchImpl knows about. Persists
- * the visibility settings and reloads them on initialization.
+ * Manages any visibility settings for all the package's databases that AppSearchImpl knows about.
+ * Persists the visibility settings and reloads them on initialization.
*
- * <p>The VisibilityStore creates a document for each database. This document holds the visibility
- * settings that apply to that database. The VisibilityStore also creates a schema for these
- * documents and has its own database so that its data doesn't interfere with any clients' data. It
- * persists the document and schema through AppSearchImpl.
+ * <p>The VisibilityStore creates a document for each package's databases. This document holds the
+ * visibility settings that apply to that package's database. The VisibilityStore also creates a
+ * schema for these documents and has its own package and database so that its data doesn't
+ * interfere with any clients' data. It persists the document and schema through AppSearchImpl.
*
* <p>These visibility settings are used to ensure AppSearch queries respect the clients' settings
* on who their data is visible to.
@@ -52,18 +55,31 @@
*/
class VisibilityStore {
/** Schema type for documents that hold AppSearch's metadata, e.g. visibility settings */
- @VisibleForTesting static final String SCHEMA_TYPE = "Visibility";
+ @VisibleForTesting static final String VISIBILITY_TYPE = "VisibilityType";
/**
* Property that holds the list of platform-hidden schemas, as part of the visibility settings.
*/
- @VisibleForTesting
- static final String NOT_PLATFORM_SURFACEABLE_PROPERTY = "notPlatformSurfaceable";
+ private static final String NOT_PLATFORM_SURFACEABLE_PROPERTY = "notPlatformSurfaceable";
- /** Schema for the VisibilityStore's docuemnts. */
- @VisibleForTesting
- static final AppSearchSchema SCHEMA =
- new AppSearchSchema.Builder(SCHEMA_TYPE)
+ /** Property that holds nested documents of package accessible schemas. */
+ private static final String PACKAGE_ACCESSIBLE_PROPERTY = "packageAccessible";
+
+ /** Schema type for nested documents that hold package accessible information. */
+ private static final String PACKAGE_ACCESSIBLE_TYPE = "PackageAccessibleType";
+
+ /** Property that holds the package name that can access a schema. */
+ private static final String PACKAGE_NAME_PROPERTY = "packageName";
+
+ /** Property that holds the SHA 256 certificate of the app that can access a schema. */
+ private static final String SHA_256_CERT_PROPERTY = "sha256Cert";
+
+ /** Property that holds the prefixed schema type that is accessible by some package. */
+ private static final String ACCESSIBLE_SCHEMA_PROPERTY = "accessibleSchema";
+
+ /** Schema for the VisibilityStore's documents. */
+ private static final AppSearchSchema VISIBILITY_SCHEMA =
+ new AppSearchSchema.Builder(VISIBILITY_TYPE)
.addProperty(
new AppSearchSchema.PropertyConfig.Builder(
NOT_PLATFORM_SURFACEABLE_PROPERTY)
@@ -71,6 +87,39 @@
.setCardinality(
AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
.build())
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder(PACKAGE_ACCESSIBLE_PROPERTY)
+ .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_DOCUMENT)
+ .setSchemaType(PACKAGE_ACCESSIBLE_TYPE)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
+ .build())
+ .build();
+
+ /**
+ * Schema for package accessible documents, these will be nested in a top-level visibility
+ * document.
+ */
+ private static final AppSearchSchema PACKAGE_ACCESSIBLE_SCHEMA =
+ new AppSearchSchema.Builder(PACKAGE_ACCESSIBLE_TYPE)
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder(PACKAGE_NAME_PROPERTY)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
+ .build())
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder(SHA_256_CERT_PROPERTY)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_BYTES)
+ .build())
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder(ACCESSIBLE_SCHEMA_PROPERTY)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
+ .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
+ .build())
.build();
/**
@@ -86,7 +135,7 @@
* database name. Tracked here to tell when we're looking at our own prefix when looking through
* AppSearchImpl.
*/
- private static final String VISIBILITY_STORE_PREFIX =
+ static final String VISIBILITY_STORE_PREFIX =
AppSearchImpl.createPrefix(PACKAGE_NAME, DATABASE_NAME);
/** Namespace of documents that contain visibility settings */
@@ -102,10 +151,23 @@
/**
* Maps prefixes to the set of schemas that are platform-hidden within that prefix. All schemas
* in the map are prefixed.
+ *
+ * <p>Although the prefix key isn't used for lookup, it's helpful in ensuring that all previous
+ * visibility settings for a prefix are completely overridden by new visibility settings.
*/
private final Map<String, Set<String>> mNotPlatformSurfaceableMap = new ArrayMap<>();
/**
+ * Maps prefixes to a an internal map. The internal map maps prefixed schemas to the set of
+ * PackageIdentifiers that have access to that schema.
+ *
+ * <p>Although the prefix key isn't used for lookup, it's helpful in ensuring that all previous
+ * visibility settings for a prefix are completely overridden by new visibility settings.
+ */
+ private final Map<String, Map<String, Set<PackageIdentifier>>> mPackageAccessibleMap =
+ new ArrayMap<>();
+
+ /**
* Creates an uninitialized VisibilityStore object. Callers must also call {@link #initialize()}
* before using the object.
*
@@ -120,19 +182,22 @@
*
* <p>This is kept separate from the constructor because this will call methods on
* AppSearchImpl. Some may even then recursively call back into VisibilityStore (for example,
- * {@link AppSearchImpl#setSchema} will call {@link #setVisibility(String, Set)}. We need to
- * have both AppSearchImpl and VisibilityStore fully initialized for this call flow to work.
+ * {@link AppSearchImpl#setSchema} will call {@link #setVisibility}. We need to have both
+ * AppSearchImpl and VisibilityStore fully initialized for this call flow to work.
*
* @throws AppSearchException AppSearchException on AppSearchImpl error.
*/
public void initialize() throws AppSearchException {
- if (!mAppSearchImpl.hasSchemaTypeLocked(PACKAGE_NAME, DATABASE_NAME, SCHEMA_TYPE)) {
+ if (!mAppSearchImpl.hasSchemaTypeLocked(PACKAGE_NAME, DATABASE_NAME, VISIBILITY_TYPE)
+ || !mAppSearchImpl.hasSchemaTypeLocked(
+ PACKAGE_NAME, DATABASE_NAME, PACKAGE_ACCESSIBLE_TYPE)) {
// Schema type doesn't exist yet. Add it.
mAppSearchImpl.setSchema(
PACKAGE_NAME,
DATABASE_NAME,
- Collections.singletonList(SCHEMA),
+ Arrays.asList(VISIBILITY_SCHEMA, PACKAGE_ACCESSIBLE_SCHEMA),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
}
@@ -153,9 +218,41 @@
NAMESPACE,
/*uri=*/ addUriPrefix(prefix));
+ // Update platform visibility settings
String[] schemas =
document.getPropertyStringArray(NOT_PLATFORM_SURFACEABLE_PROPERTY);
- mNotPlatformSurfaceableMap.put(prefix, new ArraySet<>(Arrays.asList(schemas)));
+ if (schemas != null) {
+ mNotPlatformSurfaceableMap.put(prefix, new ArraySet<>(Arrays.asList(schemas)));
+ }
+
+ // Update 3p package visibility settings
+ Map<String, Set<PackageIdentifier>> schemaToPackageIdentifierMap = new ArrayMap<>();
+ GenericDocument[] packageAccessibleDocuments =
+ document.getPropertyDocumentArray(PACKAGE_ACCESSIBLE_PROPERTY);
+ if (packageAccessibleDocuments != null) {
+ for (int i = 0; i < packageAccessibleDocuments.length; i++) {
+ String packageName =
+ packageAccessibleDocuments[i].getPropertyString(
+ PACKAGE_NAME_PROPERTY);
+ byte[] sha256Cert =
+ packageAccessibleDocuments[i].getPropertyBytes(
+ SHA_256_CERT_PROPERTY);
+ PackageIdentifier packageIdentifier =
+ new PackageIdentifier(packageName, sha256Cert);
+
+ String prefixedSchema =
+ packageAccessibleDocuments[i].getPropertyString(
+ ACCESSIBLE_SCHEMA_PROPERTY);
+ Set<PackageIdentifier> packageIdentifiers =
+ schemaToPackageIdentifierMap.get(prefixedSchema);
+ if (packageIdentifiers == null) {
+ packageIdentifiers = new ArraySet<>();
+ }
+ packageIdentifiers.add(packageIdentifier);
+ schemaToPackageIdentifierMap.put(prefixedSchema, packageIdentifiers);
+ }
+ }
+ mPackageAccessibleMap.put(prefix, schemaToPackageIdentifierMap);
} catch (AppSearchException e) {
if (e.getResultCode() == AppSearchResult.RESULT_NOT_FOUND) {
// TODO(b/172068212): This indicates some desync error. We were expecting a
@@ -176,31 +273,67 @@
* @param prefix Prefix that identifies who owns the {@code schemasNotPlatformSurfaceable}.
* @param schemasNotPlatformSurfaceable Set of prefixed schemas that should be hidden from the
* platform.
+ * @param schemasPackageAccessible Map of prefixed schemas to a list of package identifiers that
+ * have access to the schema.
* @throws AppSearchException on AppSearchImpl error.
*/
public void setVisibility(
- @NonNull String prefix, @NonNull Set<String> schemasNotPlatformSurfaceable)
+ @NonNull String prefix,
+ @NonNull Set<String> schemasNotPlatformSurfaceable,
+ @NonNull Map<String, List<PackageIdentifier>> schemasPackageAccessible)
throws AppSearchException {
Preconditions.checkNotNull(prefix);
Preconditions.checkNotNull(schemasNotPlatformSurfaceable);
+ Preconditions.checkNotNull(schemasPackageAccessible);
// Persist the document
GenericDocument.Builder visibilityDocument =
- new GenericDocument.Builder(/*uri=*/ addUriPrefix(prefix), SCHEMA_TYPE)
+ new GenericDocument.Builder(/*uri=*/ addUriPrefix(prefix), VISIBILITY_TYPE)
.setNamespace(NAMESPACE);
if (!schemasNotPlatformSurfaceable.isEmpty()) {
visibilityDocument.setPropertyString(
NOT_PLATFORM_SURFACEABLE_PROPERTY,
schemasNotPlatformSurfaceable.toArray(new String[0]));
}
+
+ Map<String, Set<PackageIdentifier>> schemaToPackageIdentifierMap = new ArrayMap<>();
+ List<GenericDocument> packageAccessibleDocuments = new ArrayList<>();
+ for (Map.Entry<String, List<PackageIdentifier>> entry :
+ schemasPackageAccessible.entrySet()) {
+ for (int i = 0; i < entry.getValue().size(); i++) {
+ // TODO(b/169883602): remove the "placeholder" uri once upstream changes to relax
+ // nested
+ // document uri rules gets synced down.
+ GenericDocument packageAccessibleDocument =
+ new GenericDocument.Builder(/*uri=*/ "placeholder", PACKAGE_ACCESSIBLE_TYPE)
+ .setNamespace(NAMESPACE)
+ .setPropertyString(
+ PACKAGE_NAME_PROPERTY,
+ entry.getValue().get(i).getPackageName())
+ .setPropertyBytes(
+ SHA_256_CERT_PROPERTY,
+ entry.getValue().get(i).getSha256Certificate())
+ .setPropertyString(ACCESSIBLE_SCHEMA_PROPERTY, entry.getKey())
+ .build();
+ packageAccessibleDocuments.add(packageAccessibleDocument);
+ }
+ schemaToPackageIdentifierMap.put(entry.getKey(), new ArraySet<>(entry.getValue()));
+ }
+ if (!packageAccessibleDocuments.isEmpty()) {
+ visibilityDocument.setPropertyDocument(
+ PACKAGE_ACCESSIBLE_PROPERTY,
+ packageAccessibleDocuments.toArray(new GenericDocument[0]));
+ }
+
mAppSearchImpl.putDocument(PACKAGE_NAME, DATABASE_NAME, visibilityDocument.build());
// Update derived data structures.
mNotPlatformSurfaceableMap.put(prefix, schemasNotPlatformSurfaceable);
+ mPackageAccessibleMap.put(prefix, schemaToPackageIdentifierMap);
}
/** Returns if the schema is surfaceable by the platform. */
- @NonNull
+ // TODO(b/169883602): check permissions against the allowlisted global querier package name.
public boolean isSchemaPlatformSurfaceable(
@NonNull String prefix, @NonNull String prefixedSchema) {
Preconditions.checkNotNull(prefix);
@@ -212,6 +345,31 @@
return !notPlatformSurfaceableSchemas.contains(prefixedSchema);
}
+ /** Returns whether the schema is accessible by {@code accessingPackage}. */
+ // TODO(b/169883602): check certificate and package against the incoming querier's uid/package.
+ public boolean isSchemaPackageAccessible(
+ @NonNull String prefix,
+ @NonNull String prefixedSchema,
+ @NonNull PackageIdentifier accessingPackage) {
+ Preconditions.checkNotNull(prefix);
+ Preconditions.checkNotNull(prefixedSchema);
+ Preconditions.checkNotNull(accessingPackage);
+
+ Map<String, Set<PackageIdentifier>> schemaToPackageIdentifierMap =
+ mPackageAccessibleMap.get(prefix);
+ if (schemaToPackageIdentifierMap == null) {
+ return false;
+ }
+
+ Set<PackageIdentifier> packageIdentifiers =
+ schemaToPackageIdentifierMap.get(prefixedSchema);
+ if (packageIdentifiers == null) {
+ return false;
+ }
+
+ return packageIdentifiers.contains(accessingPackage);
+ }
+
/**
* Handles an {@code AppSearchImpl#reset()} by clearing any cached state.
*
@@ -219,6 +377,7 @@
*/
void handleReset() {
mNotPlatformSurfaceableMap.clear();
+ mPackageAccessibleMap.clear();
}
/**
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
index 814ee4f..073a7f6 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
@@ -26,6 +26,9 @@
import com.google.android.icing.proto.SearchSpecProto;
import com.google.android.icing.proto.TermMatchType;
+import java.util.List;
+import java.util.Map;
+
/**
* Translates a {@link SearchSpec} into icing search protos.
*
@@ -57,14 +60,22 @@
@NonNull
public static ResultSpecProto toResultSpecProto(@NonNull SearchSpec spec) {
Preconditions.checkNotNull(spec);
- return ResultSpecProto.newBuilder()
- .setNumPerPage(spec.getResultCountPerPage())
- .setSnippetSpec(
- ResultSpecProto.SnippetSpecProto.newBuilder()
- .setNumToSnippet(spec.getSnippetCount())
- .setNumMatchesPerProperty(spec.getSnippetCountPerProperty())
- .setMaxWindowBytes(spec.getMaxSnippetSize()))
- .build();
+ ResultSpecProto.Builder builder =
+ ResultSpecProto.newBuilder()
+ .setNumPerPage(spec.getResultCountPerPage())
+ .setSnippetSpec(
+ ResultSpecProto.SnippetSpecProto.newBuilder()
+ .setNumToSnippet(spec.getSnippetCount())
+ .setNumMatchesPerProperty(spec.getSnippetCountPerProperty())
+ .setMaxWindowBytes(spec.getMaxSnippetSize()));
+ Map<String, List<String>> projectionTypePropertyPaths = spec.getProjections();
+ for (Map.Entry<String, List<String>> e : projectionTypePropertyPaths.entrySet()) {
+ builder.addTypePropertyMasks(
+ ResultSpecProto.TypePropertyMask.newBuilder()
+ .setSchemaType(e.getKey())
+ .addAllPaths(e.getValue()));
+ }
+ return builder.build();
}
/** Extracts {@link ScoringSpecProto} information from a {@link SearchSpec}. */
@@ -79,17 +90,28 @@
if (orderCodeProto == null) {
throw new IllegalArgumentException("Invalid result ranking order: " + orderCode);
}
- protoBuilder.setOrderBy(orderCodeProto);
-
- @SearchSpec.RankingStrategy int rankingStrategyCode = spec.getRankingStrategy();
- ScoringSpecProto.RankingStrategy.Code rankingStrategyCodeProto =
- ScoringSpecProto.RankingStrategy.Code.forNumber(rankingStrategyCode);
- if (rankingStrategyCodeProto == null) {
- throw new IllegalArgumentException(
- "Invalid result ranking strategy: " + rankingStrategyCode);
- }
- protoBuilder.setRankBy(rankingStrategyCodeProto);
+ protoBuilder
+ .setOrderBy(orderCodeProto)
+ .setRankBy(toProtoRankingStrategy(spec.getRankingStrategy()));
return protoBuilder.build();
}
+
+ private static ScoringSpecProto.RankingStrategy.Code toProtoRankingStrategy(
+ @SearchSpec.RankingStrategy int rankingStrategyCode) {
+ switch (rankingStrategyCode) {
+ case SearchSpec.RANKING_STRATEGY_NONE:
+ return ScoringSpecProto.RankingStrategy.Code.NONE;
+ case SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE:
+ return ScoringSpecProto.RankingStrategy.Code.DOCUMENT_SCORE;
+ case SearchSpec.RANKING_STRATEGY_CREATION_TIMESTAMP:
+ return ScoringSpecProto.RankingStrategy.Code.CREATION_TIMESTAMP;
+ case SearchSpec.RANKING_STRATEGY_RELEVANCE_SCORE:
+ return ScoringSpecProto.RankingStrategy.Code
+ .RELEVANCE_SCORE_NONFUNCTIONAL_PLACEHOLDER;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid result ranking strategy: " + rankingStrategyCode);
+ }
+ }
}
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index 73f64dc..f8e5a8a 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-I8b7425b3f87153547d1c8f5b560be5a54c9be97e
+I6745091e5cb97d69ce2e5f85d3d15c073e7e3ef7
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
index 39f7526..38500af 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java
@@ -89,8 +89,8 @@
* <p> Before committing the session, apps can indicate which apps are allowed to access the
* contributed data using one or more of the following access modes:
* <ul>
- * <li> {@link Session#allowPackageAccess(String, byte[])} which will allow whitelisting
- * specific packages to access the blobs.
+ * <li> {@link Session#allowPackageAccess(String, byte[])} which will allow specific packages
+ * to access the blobs.
* <li> {@link Session#allowSameSignatureAccess()} which will allow only apps which are signed
* with the same certificate as the app which contributed the blob to access it.
* <li> {@link Session#allowPublicAccess()} which will allow any app on the device to access
diff --git a/apex/blobstore/framework/java/android/app/blob/XmlTags.java b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
index 656749d..bfc5826 100644
--- a/apex/blobstore/framework/java/android/app/blob/XmlTags.java
+++ b/apex/blobstore/framework/java/android/app/blob/XmlTags.java
@@ -36,7 +36,7 @@
// For BlobAccessMode
public static final String TAG_ACCESS_MODE = "am";
public static final String ATTR_TYPE = "t";
- public static final String TAG_WHITELISTED_PACKAGE = "wl";
+ public static final String TAG_ALLOWED_PACKAGE = "wl";
public static final String ATTR_CERTIFICATE = "ct";
// For BlobHandle
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
index ba0fab6..4a527ad 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java
@@ -18,7 +18,7 @@
import static android.app.blob.XmlTags.ATTR_CERTIFICATE;
import static android.app.blob.XmlTags.ATTR_PACKAGE;
import static android.app.blob.XmlTags.ATTR_TYPE;
-import static android.app.blob.XmlTags.TAG_WHITELISTED_PACKAGE;
+import static android.app.blob.XmlTags.TAG_ALLOWED_PACKAGE;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -52,21 +52,21 @@
ACCESS_TYPE_PRIVATE,
ACCESS_TYPE_PUBLIC,
ACCESS_TYPE_SAME_SIGNATURE,
- ACCESS_TYPE_WHITELIST,
+ ACCESS_TYPE_ALLOWLIST,
})
@interface AccessType {}
public static final int ACCESS_TYPE_PRIVATE = 1 << 0;
public static final int ACCESS_TYPE_PUBLIC = 1 << 1;
public static final int ACCESS_TYPE_SAME_SIGNATURE = 1 << 2;
- public static final int ACCESS_TYPE_WHITELIST = 1 << 3;
+ public static final int ACCESS_TYPE_ALLOWLIST = 1 << 3;
private int mAccessType = ACCESS_TYPE_PRIVATE;
- private final ArraySet<PackageIdentifier> mWhitelistedPackages = new ArraySet<>();
+ private final ArraySet<PackageIdentifier> mAllowedPackages = new ArraySet<>();
void allow(BlobAccessMode other) {
- if ((other.mAccessType & ACCESS_TYPE_WHITELIST) != 0) {
- mWhitelistedPackages.addAll(other.mWhitelistedPackages);
+ if ((other.mAccessType & ACCESS_TYPE_ALLOWLIST) != 0) {
+ mAllowedPackages.addAll(other.mAllowedPackages);
}
mAccessType |= other.mAccessType;
}
@@ -80,8 +80,8 @@
}
void allowPackageAccess(@NonNull String packageName, @NonNull byte[] certificate) {
- mAccessType |= ACCESS_TYPE_WHITELIST;
- mWhitelistedPackages.add(PackageIdentifier.create(packageName, certificate));
+ mAccessType |= ACCESS_TYPE_ALLOWLIST;
+ mAllowedPackages.add(PackageIdentifier.create(packageName, certificate));
}
boolean isPublicAccessAllowed() {
@@ -93,10 +93,10 @@
}
boolean isPackageAccessAllowed(@NonNull String packageName, @NonNull byte[] certificate) {
- if ((mAccessType & ACCESS_TYPE_WHITELIST) == 0) {
+ if ((mAccessType & ACCESS_TYPE_ALLOWLIST) == 0) {
return false;
}
- return mWhitelistedPackages.contains(PackageIdentifier.create(packageName, certificate));
+ return mAllowedPackages.contains(PackageIdentifier.create(packageName, certificate));
}
boolean isAccessAllowedForCaller(Context context,
@@ -113,9 +113,9 @@
}
}
- if ((mAccessType & ACCESS_TYPE_WHITELIST) != 0) {
- for (int i = 0; i < mWhitelistedPackages.size(); ++i) {
- final PackageIdentifier packageIdentifier = mWhitelistedPackages.valueAt(i);
+ if ((mAccessType & ACCESS_TYPE_ALLOWLIST) != 0) {
+ for (int i = 0; i < mAllowedPackages.size(); ++i) {
+ final PackageIdentifier packageIdentifier = mAllowedPackages.valueAt(i);
if (packageIdentifier.packageName.equals(callingPackage)
&& pm.hasSigningCertificate(callingPackage, packageIdentifier.certificate,
PackageManager.CERT_INPUT_SHA256)) {
@@ -131,20 +131,20 @@
return mAccessType;
}
- int getNumWhitelistedPackages() {
- return mWhitelistedPackages.size();
+ int getAllowedPackagesCount() {
+ return mAllowedPackages.size();
}
void dump(IndentingPrintWriter fout) {
fout.println("accessType: " + DebugUtils.flagsToString(
BlobAccessMode.class, "ACCESS_TYPE_", mAccessType));
- fout.print("Whitelisted pkgs:");
- if (mWhitelistedPackages.isEmpty()) {
+ fout.print("Explicitly allowed pkgs:");
+ if (mAllowedPackages.isEmpty()) {
fout.println(" (Empty)");
} else {
fout.increaseIndent();
- for (int i = 0, count = mWhitelistedPackages.size(); i < count; ++i) {
- fout.println(mWhitelistedPackages.valueAt(i).toString());
+ for (int i = 0, count = mAllowedPackages.size(); i < count; ++i) {
+ fout.println(mAllowedPackages.valueAt(i).toString());
}
fout.decreaseIndent();
}
@@ -152,12 +152,12 @@
void writeToXml(@NonNull XmlSerializer out) throws IOException {
XmlUtils.writeIntAttribute(out, ATTR_TYPE, mAccessType);
- for (int i = 0, count = mWhitelistedPackages.size(); i < count; ++i) {
- out.startTag(null, TAG_WHITELISTED_PACKAGE);
- final PackageIdentifier packageIdentifier = mWhitelistedPackages.valueAt(i);
+ for (int i = 0, count = mAllowedPackages.size(); i < count; ++i) {
+ out.startTag(null, TAG_ALLOWED_PACKAGE);
+ final PackageIdentifier packageIdentifier = mAllowedPackages.valueAt(i);
XmlUtils.writeStringAttribute(out, ATTR_PACKAGE, packageIdentifier.packageName);
XmlUtils.writeByteArrayAttribute(out, ATTR_CERTIFICATE, packageIdentifier.certificate);
- out.endTag(null, TAG_WHITELISTED_PACKAGE);
+ out.endTag(null, TAG_ALLOWED_PACKAGE);
}
}
@@ -171,7 +171,7 @@
final int depth = in.getDepth();
while (XmlUtils.nextElementWithin(in, depth)) {
- if (TAG_WHITELISTED_PACKAGE.equals(in.getName())) {
+ if (TAG_ALLOWED_PACKAGE.equals(in.getName())) {
final String packageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE);
final byte[] certificate = XmlUtils.readByteArrayAttribute(in, ATTR_CERTIFICATE);
blobAccessMode.allowPackageAccess(packageName, certificate);
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
index 9850b5d..fb02e96 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobMetadata.java
@@ -479,7 +479,7 @@
proto.write(BlobStatsEventProto.BlobCommitterProto.ACCESS_MODE,
committer.blobAccessMode.getAccessType());
proto.write(BlobStatsEventProto.BlobCommitterProto.NUM_WHITELISTED_PACKAGE,
- committer.blobAccessMode.getNumWhitelistedPackages());
+ committer.blobAccessMode.getAllowedPackagesCount());
proto.end(token);
}
final byte[] committersBytes = proto.getBytes();
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index 2f83be1..fe68882 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -332,10 +332,10 @@
throw new IllegalStateException("Not allowed to change access type in state: "
+ stateToString(mState));
}
- if (mBlobAccessMode.getNumWhitelistedPackages() >= getMaxPermittedPackages()) {
+ if (mBlobAccessMode.getAllowedPackagesCount() >= getMaxPermittedPackages()) {
throw new ParcelableException(new LimitExceededException(
"Too many packages permitted to access the blob: "
- + mBlobAccessMode.getNumWhitelistedPackages()));
+ + mBlobAccessMode.getAllowedPackagesCount()));
}
mBlobAccessMode.allowPackageAccess(packageName, certificate);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 35dadf0..97ba815 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -2399,7 +2399,12 @@
return false;
}
- if (checkIfRestricted(job) != null) {
+ final JobRestriction restriction = checkIfRestricted(job);
+ if (restriction != null) {
+ if (DEBUG) {
+ Slog.v(TAG, "areComponentsInPlaceLocked: " + job.toShortString()
+ + " restricted due to " + restriction.getReason());
+ }
return false;
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index a9ca730..26b5abe 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -260,11 +260,9 @@
try {
final int bindFlags;
if (job.shouldTreatAsExpeditedJob()) {
- // Add BIND_FOREGROUND_SERVICE to make it BFGS. Without it, it'll be
- // PROCESS_STATE_IMPORTANT_FOREGROUND. Unclear which is better here.
// TODO(171305774): The job should run on the little cores. We'll probably need
// another binding flag for that.
- bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
+ bindFlags = Context.BIND_AUTO_CREATE;
} else {
bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
| Context.BIND_NOT_PERCEPTIBLE;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index d5130dc..e8a2817 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -228,6 +228,23 @@
return;
}
+ if (jobStatus.shouldTreatAsExpeditedJob()) {
+ if (!jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY)) {
+ // Don't request a direct hole through any of the firewalls. Instead, mark the
+ // constraint as satisfied if the network is available, and the job will get
+ // through the firewalls once it starts running and the proc state is elevated.
+ // This is the same behavior that FGS see.
+ updateConstraintsSatisfied(jobStatus);
+ }
+ // Don't need to update constraint here if the network goes away. We'll do that as part
+ // of regular processing when we're notified about the drop.
+ } else if (jobStatus.isRequestedExpeditedJob()
+ && jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY)) {
+ // Make sure we don't accidentally keep the constraint as satisfied if the job went
+ // from being expedited-ready to not-expeditable.
+ updateConstraintsSatisfied(jobStatus);
+ }
+
// Always check the full job readiness stat in case the component has been disabled.
if (wouldBeReadyWithConstraintLocked(jobStatus, JobStatus.CONSTRAINT_CONNECTIVITY)
&& isNetworkAvailable(jobStatus)) {
@@ -442,7 +459,8 @@
}
private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
- final Network network = mConnManager.getActiveNetworkForUid(jobStatus.getSourceUid());
+ final Network network = mConnManager.getActiveNetworkForUid(
+ jobStatus.getSourceUid(), jobStatus.shouldIgnoreNetworkBlocking());
final NetworkCapabilities capabilities = getNetworkCapabilities(network);
return updateConstraintsSatisfied(jobStatus, network, capabilities);
}
@@ -503,20 +521,42 @@
return false;
}
- final Network network = mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid());
+ final Network network =
+ mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid(), false);
final NetworkCapabilities capabilities = getNetworkCapabilities(network);
final boolean networkMatch = (filterNetwork == null
|| Objects.equals(filterNetwork, network));
+ boolean exemptedLoaded = false;
+ Network exemptedNetwork = null;
+ NetworkCapabilities exemptedNetworkCapabilities = null;
+ boolean exemptedNetworkMatch = false;
boolean changed = false;
for (int i = jobs.size() - 1; i >= 0; i--) {
final JobStatus js = jobs.valueAt(i);
+ Network net = network;
+ NetworkCapabilities netCap = capabilities;
+ boolean match = networkMatch;
+
+ if (js.shouldIgnoreNetworkBlocking()) {
+ if (!exemptedLoaded) {
+ exemptedLoaded = true;
+ exemptedNetwork = mConnManager.getActiveNetworkForUid(js.getSourceUid(), true);
+ exemptedNetworkCapabilities = getNetworkCapabilities(exemptedNetwork);
+ exemptedNetworkMatch = (filterNetwork == null
+ || Objects.equals(filterNetwork, exemptedNetwork));
+ }
+ net = exemptedNetwork;
+ netCap = exemptedNetworkCapabilities;
+ match = exemptedNetworkMatch;
+ }
+
// Update either when we have a network match, or when the
// job hasn't yet been evaluated against the currently
// active network; typically when we just lost a network.
- if (networkMatch || !Objects.equals(js.network, network)) {
- changed |= updateConstraintsSatisfied(js, network, capabilities);
+ if (match || !Objects.equals(js.network, net)) {
+ changed |= updateConstraintsSatisfied(js, net, netCap);
}
}
return changed;
diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt
index ce3bcbe..103bb47 100644
--- a/apex/media/framework/api/current.txt
+++ b/apex/media/framework/api/current.txt
@@ -6,9 +6,11 @@
method public int describeContents();
method @NonNull public java.util.List<java.lang.String> getSupportedHdrTypes();
method @NonNull public java.util.List<java.lang.String> getSupportedVideoMimeTypes();
- method public boolean isHdrTypeSupported(@NonNull String);
+ method @NonNull public java.util.List<java.lang.String> getUnsupportedHdrTypes();
+ method @NonNull public java.util.List<java.lang.String> getUnsupportedVideoMimeTypes();
+ method public boolean isHdrTypeSupported(@NonNull String) throws android.media.ApplicationMediaCapabilities.FormatNotFoundException;
method public boolean isSlowMotionSupported();
- method public boolean isVideoMimeTypeSupported(@NonNull String);
+ method public boolean isVideoMimeTypeSupported(@NonNull String) throws android.media.ApplicationMediaCapabilities.FormatNotFoundException;
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.ApplicationMediaCapabilities> CREATOR;
}
@@ -17,10 +19,16 @@
ctor public ApplicationMediaCapabilities.Builder();
method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedHdrType(@NonNull String);
method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedVideoMimeType(@NonNull String);
+ method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedHdrType(@NonNull String);
+ method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedVideoMimeType(@NonNull String);
method @NonNull public android.media.ApplicationMediaCapabilities build();
method @NonNull public android.media.ApplicationMediaCapabilities.Builder setSlowMotionSupported(boolean);
}
+ public static class ApplicationMediaCapabilities.FormatNotFoundException extends android.util.AndroidException {
+ ctor public ApplicationMediaCapabilities.FormatNotFoundException(@NonNull String);
+ }
+
public class MediaController2 implements java.lang.AutoCloseable {
method public void cancelSessionCommand(@NonNull Object);
method public void close();
diff --git a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
index 36f6b94..25ccec2 100644
--- a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
+++ b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
@@ -22,6 +22,7 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.AndroidException;
import android.util.Log;
import org.xmlpull.v1.XmlPullParser;
@@ -68,35 +69,73 @@
public final class ApplicationMediaCapabilities implements Parcelable {
private static final String TAG = "ApplicationMediaCapabilities";
+ /**
+ * This exception is thrown when a given format is not specified in the media capabilities.
+ */
+ public static class FormatNotFoundException extends AndroidException {
+ public FormatNotFoundException(@NonNull String format) {
+ super(format);
+ }
+ }
+
/** List of supported video codec mime types. */
// TODO: init it with avc and mpeg4 as application is assuming to support them.
private Set<String> mSupportedVideoMimeTypes = new HashSet<>();
+ /** List of unsupported video codec mime types. */
+ private Set<String> mUnsupportedVideoMimeTypes = new HashSet<>();
+
/** List of supported hdr types. */
private Set<String> mSupportedHdrTypes = new HashSet<>();
+ /** List of unsupported hdr types. */
+ private Set<String> mUnsupportedHdrTypes = new HashSet<>();
+
private boolean mIsSlowMotionSupported = false;
private ApplicationMediaCapabilities(Builder b) {
mSupportedVideoMimeTypes.addAll(b.getSupportedVideoMimeTypes());
+ mUnsupportedVideoMimeTypes.addAll(b.getUnsupportedVideoMimeTypes());
mSupportedHdrTypes.addAll(b.getSupportedHdrTypes());
+ mUnsupportedHdrTypes.addAll(b.getUnsupportedHdrTypes());
mIsSlowMotionSupported = b.mIsSlowMotionSupported;
}
/**
- * Query if an video codec is supported by the application.
+ * Query if a video codec format is supported by the application.
+ * @param videoMime The mime type of the video codec format. Must be the one used in
+ * {@link MediaFormat#KEY_MIME}.
+ * @return true if application supports the video codec format, false otherwise.
+ * @throws FormatNotFoundException if the application did not specify the codec either in the
+ * supported or unsupported formats.
*/
public boolean isVideoMimeTypeSupported(
- @NonNull String videoMime) {
- return mSupportedVideoMimeTypes.contains(videoMime);
+ @NonNull String videoMime) throws FormatNotFoundException {
+ if (mUnsupportedVideoMimeTypes.contains(videoMime)) {
+ return false;
+ } else if (mSupportedVideoMimeTypes.contains(videoMime)) {
+ return true;
+ } else {
+ throw new FormatNotFoundException(videoMime);
+ }
}
/**
- * Query if a hdr type is supported by the application.
+ * Query if a HDR type is supported by the application.
+ * @param hdrType The type of the HDR format.
+ * @return true if application supports the HDR format, false otherwise.
+ * @throws FormatNotFoundException if the application did not specify the format either in the
+ * supported or unsupported formats.
*/
public boolean isHdrTypeSupported(
- @NonNull @MediaFeature.MediaHdrType String hdrType) {
- return mSupportedHdrTypes.contains(hdrType);
+ @NonNull @MediaFeature.MediaHdrType String hdrType) throws FormatNotFoundException {
+ if (mUnsupportedHdrTypes.contains(hdrType)) {
+ return false;
+ } else if (mSupportedHdrTypes.contains(hdrType)) {
+ return true;
+ } else {
+ throw new FormatNotFoundException(hdrType);
+ }
}
@Override
@@ -111,11 +150,21 @@
for (String cap : mSupportedVideoMimeTypes) {
dest.writeString(cap);
}
+ // Write out the unsupported video mime types.
+ dest.writeInt(mUnsupportedVideoMimeTypes.size());
+ for (String cap : mUnsupportedVideoMimeTypes) {
+ dest.writeString(cap);
+ }
// Write out the supported hdr types.
dest.writeInt(mSupportedHdrTypes.size());
for (String cap : mSupportedHdrTypes) {
dest.writeString(cap);
}
+ // Write out the unsupported hdr types.
+ dest.writeInt(mUnsupportedHdrTypes.size());
+ for (String cap : mUnsupportedHdrTypes) {
+ dest.writeString(cap);
+ }
// Write out the supported slow motion.
dest.writeBoolean(mIsSlowMotionSupported);
}
@@ -124,7 +173,9 @@
public String toString() {
String caps = new String(
"Supported Video MimeTypes: " + mSupportedVideoMimeTypes.toString());
+ caps += "Unsupported Video MimeTypes: " + mUnsupportedVideoMimeTypes.toString();
caps += "Supported HDR types: " + mSupportedHdrTypes.toString();
+ caps += "Unsupported HDR types: " + mUnsupportedHdrTypes.toString();
caps += "Supported slow motion: " + mIsSlowMotionSupported;
return caps;
}
@@ -159,9 +210,8 @@
};
/*
- * Returns a list that contains all the video codec mime types supported by the application.
- * The list will be empty if no codecs are supported by the application.
- * @return List of supported video codec mime types.
+ * Query the video codec mime types supported by the application.
+ * @return List of supported video codec mime types. The list will be empty if there are none.
*/
@NonNull
public List<String> getSupportedVideoMimeTypes() {
@@ -169,9 +219,17 @@
}
/*
- * Returns a list that contains all hdr types supported by the application.
- * The list will be empty if no hdr types are supported by the application.
- * @return List of supported hdr types.
+ * Query the video codec mime types that are not supported by the application.
+ * @return List of unsupported video codec mime types. The list will be empty if there are none.
+ */
+ @NonNull
+ public List<String> getUnsupportedVideoMimeTypes() {
+ return new ArrayList<>(mSupportedVideoMimeTypes);
+ }
+
+ /*
+ * Query all hdr types that are supported by the application.
+ * @return List of supported hdr types. The list will be empty if there are none.
*/
@NonNull
public List<String> getSupportedHdrTypes() {
@@ -179,6 +237,15 @@
}
/*
+ * Query all hdr types that are not supported by the application.
+ * @return List of unsupported hdr types. The list will be empty if there are none.
+ */
+ @NonNull
+ public List<String> getUnsupportedHdrTypes() {
+ return new ArrayList<>(mUnsupportedHdrTypes);
+ }
+
+ /*
* Whether handling of slow-motion video is supported
*/
public boolean isSlowMotionSupported() {
@@ -213,6 +280,12 @@
/** List of supported hdr types. */
private Set<String> mSupportedHdrTypes = new HashSet<>();
+ /** List of unsupported video codec mime types. */
+ private Set<String> mUnsupportedVideoMimeTypes = new HashSet<>();
+
+ /** List of unsupported hdr types. */
+ private Set<String> mUnsupportedHdrTypes = new HashSet<>();
+
private boolean mIsSlowMotionSupported = false;
/* Map to save the format read from the xml. */
@@ -299,26 +372,50 @@
case "HEVC":
if (isSupported) {
mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
+ } else {
+ mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
+ }
+ break;
+ case "VP9":
+ if (isSupported) {
+ mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9);
+ } else {
+ mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9);
+ }
+ break;
+ case "AV1":
+ if (isSupported) {
+ mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+ } else {
+ mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1);
}
break;
case "HDR10":
if (isSupported) {
mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10);
+ } else {
+ mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10);
}
break;
case "HDR10Plus":
if (isSupported) {
mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS);
+ } else {
+ mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS);
}
break;
case "Dolby-Vision":
if (isSupported) {
mSupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION);
+ } else {
+ mUnsupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION);
}
break;
case "HLG":
if (isSupported) {
mSupportedHdrTypes.add(MediaFeature.HdrType.HLG);
+ } else {
+ mUnsupportedHdrTypes.add(MediaFeature.HdrType.HLG);
}
break;
case "SlowMotion":
@@ -348,8 +445,11 @@
@NonNull
public ApplicationMediaCapabilities build() {
Log.d(TAG,
- "Building ApplicationMediaCapabilities with: " + mSupportedHdrTypes.toString()
- + " " + mSupportedVideoMimeTypes.toString() + " "
+ "Building ApplicationMediaCapabilities with: (Supported HDR: "
+ + mSupportedHdrTypes.toString() + " Unsupported HDR: "
+ + mUnsupportedHdrTypes.toString() + ") (Supported Codec: "
+ + " " + mSupportedVideoMimeTypes.toString() + " Unsupported Codec:"
+ + mUnsupportedVideoMimeTypes.toString() + ") "
+ mIsSlowMotionSupported);
// If hdr is supported, application must also support hevc.
@@ -365,8 +465,7 @@
*
* @param codecMime Supported codec mime types. Must be one of the mime type defined
* in {@link MediaFormat}.
- * @throws UnsupportedOperationException if the codec mime type is not supported.
- * @throws IllegalArgumentException if mime type is not valid.
+ * @throws IllegalArgumentException if mime type is not valid.
*/
@NonNull
public Builder addSupportedVideoMimeType(
@@ -379,16 +478,49 @@
return new ArrayList<>(mSupportedVideoMimeTypes);
}
+ private boolean isValidVideoCodecMimeType(@NonNull String codecMime) {
+ if (!codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)
+ && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)
+ && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Adds an unsupported video codec mime type.
+ *
+ * @param codecMime Unsupported codec mime type. Must be one of the mime type defined
+ * in {@link MediaFormat}.
+ * @throws IllegalArgumentException if mime type is not valid.
+ */
+ @NonNull
+ public Builder addUnsupportedVideoMimeType(
+ @NonNull String codecMime) {
+ if (!isValidVideoCodecMimeType(codecMime)) {
+ throw new IllegalArgumentException("Invalid codec mime type: " + codecMime);
+ }
+ mUnsupportedVideoMimeTypes.add(codecMime);
+ return this;
+ }
+
+ private List<String> getUnsupportedVideoMimeTypes() {
+ return new ArrayList<>(mUnsupportedVideoMimeTypes);
+ }
+
/**
* Adds a supported hdr type.
*
- * @param hdrType Supported hdr types. Must be one of the String defined in
+ * @param hdrType Supported hdr type. Must be one of the String defined in
* {@link MediaFeature.HdrType}.
* @throws IllegalArgumentException if hdrType is not valid.
*/
@NonNull
public Builder addSupportedHdrType(
@NonNull @MediaFeature.MediaHdrType String hdrType) {
+ if (!isValidVideoCodecHdrType(hdrType)) {
+ throw new IllegalArgumentException("Invalid hdr type: " + hdrType);
+ }
mSupportedHdrTypes.add(hdrType);
return this;
}
@@ -397,6 +529,37 @@
return new ArrayList<>(mSupportedHdrTypes);
}
+ private boolean isValidVideoCodecHdrType(@NonNull String hdrType) {
+ if (!hdrType.equals(MediaFeature.HdrType.DOLBY_VISION)
+ && !hdrType.equals(MediaFeature.HdrType.HDR10)
+ && !hdrType.equals(MediaFeature.HdrType.HDR10_PLUS)
+ && !hdrType.equals(MediaFeature.HdrType.HLG)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Adds an unsupported hdr type.
+ *
+ * @param hdrType Unsupported hdr type. Must be one of the String defined in
+ * {@link MediaFeature.HdrType}.
+ * @throws IllegalArgumentException if hdrType is not valid.
+ */
+ @NonNull
+ public Builder addUnsupportedHdrType(
+ @NonNull @MediaFeature.MediaHdrType String hdrType) {
+ if (!isValidVideoCodecHdrType(hdrType)) {
+ throw new IllegalArgumentException("Invalid hdr type: " + hdrType);
+ }
+ mUnsupportedHdrTypes.add(hdrType);
+ return this;
+ }
+
+ private List<String> getUnsupportedHdrTypes() {
+ return new ArrayList<>(mUnsupportedHdrTypes);
+ }
+
/**
* Sets whether slow-motion video is supported.
* If an application indicates support for slow-motion, it is application's responsibility
diff --git a/apex/media/framework/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java
index 3d706e4..55c4629 100644
--- a/apex/media/framework/java/android/media/MediaTranscodeManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java
@@ -980,8 +980,15 @@
throw new UnsupportedOperationException(
"Source video format hint must be set!");
}
- boolean supportHevc = mClientCaps.isVideoMimeTypeSupported(
- MediaFormat.MIMETYPE_VIDEO_HEVC);
+
+ boolean supportHevc = false;
+ try {
+ supportHevc = mClientCaps.isVideoMimeTypeSupported(
+ MediaFormat.MIMETYPE_VIDEO_HEVC);
+ } catch (ApplicationMediaCapabilities.FormatNotFoundException ex) {
+ // Set to false if application did not specify.
+ supportHevc = false;
+ }
if (!supportHevc && MediaFormat.MIMETYPE_VIDEO_HEVC.equals(
mSrcVideoFormatHint.getString(MediaFormat.KEY_MIME))) {
return true;
@@ -1016,13 +1023,11 @@
"Source Width and height must be larger than 0");
}
- // TODO(hkuang): Remove the hardcoded frameRate after b/176940364 is fixed.
- float frameRate = (float) 30.0;
- /*mSrcVideoFormatHint.getFloat(MediaFormat.KEY_FRAME_RATE, frameRate);
+ float frameRate = mSrcVideoFormatHint.getFloat(MediaFormat.KEY_FRAME_RATE);
if (frameRate <= 0) {
throw new IllegalArgumentException(
"frameRate must be larger than 0");
- }*/
+ }
int bitrate = getAVCBitrate(width, height, frameRate);
videoTrackFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 5af84b0..a0cc407 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -103,9 +103,18 @@
std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) {
std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader());
+ if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_)) {
+ return nullptr;
+ }
+
+ if (idmap_header->magic_ != kIdmapMagic ||
+ idmap_header->version_ != kIdmapCurrentVersion) {
+ // Do not continue parsing if the file is not a current version idmap.
+ return nullptr;
+ }
+
uint32_t enforce_overlayable;
- if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) ||
- !Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) ||
+ if (!Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) ||
!Read32(stream, &idmap_header->fulfilled_policies_) ||
!Read32(stream, &enforce_overlayable) || !ReadString(stream, &idmap_header->target_path_) ||
!ReadString(stream, &idmap_header->overlay_path_) ||
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index 9abb9e4..46eeb8e 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -285,14 +285,12 @@
bool enforce_overlayable,
LogInfo& log_info) {
AssetManager2 target_asset_manager;
- if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true /* invalidate_caches */,
- false /* filter_incompatible_configs*/)) {
+ if (!target_asset_manager.SetApkAssets({&target_apk_assets})) {
return Error("failed to create target asset manager");
}
AssetManager2 overlay_asset_manager;
- if (!overlay_asset_manager.SetApkAssets({&overlay_apk_assets}, true /* invalidate_caches */,
- false /* filter_incompatible_configs */)) {
+ if (!overlay_asset_manager.SetApkAssets({&overlay_apk_assets})) {
return Error("failed to create overlay asset manager");
}
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index c13b049..16b68f0 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -76,6 +76,24 @@
ASSERT_EQ(header->GetDebugInfo(), "debug");
}
+TEST(IdmapTests, IdmapFailParsingDifferentVersion) {
+ constexpr size_t kJunkSize = 2000;
+ std::stringstream stream;
+ stream << android::kIdmapMagic;
+ stream << 0xffffffffU;
+ stream << std::string(kJunkSize, (char) 0xffU);
+ ASSERT_FALSE(Idmap::FromBinaryStream(stream));
+}
+
+TEST(IdmapTests, IdmapFailParsingDifferentMagic) {
+ constexpr size_t kJunkSize = 2000;
+ std::stringstream stream;
+ stream << 0xffffffffU;
+ stream << android::kIdmapCurrentVersion;
+ stream << std::string(kJunkSize, (char) 0xffU);
+ ASSERT_FALSE(Idmap::FromBinaryStream(stream));
+}
+
TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
const size_t offset = kIdmapRawDataOffset;
std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
@@ -425,11 +443,7 @@
std::stringstream bad_magic_stream(bad_magic_string);
std::unique_ptr<const IdmapHeader> bad_magic_header =
IdmapHeader::FromBinaryStream(bad_magic_stream);
- ASSERT_THAT(bad_magic_header, NotNull());
- ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic());
- ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
- target_crc, overlay_crc, policies,
- /* enforce_overlayable */ true));
+ ASSERT_EQ(nullptr, bad_magic_header);
// version: bytes (0x4, 0x07)
std::string bad_version_string(stream.str());
@@ -440,11 +454,7 @@
std::stringstream bad_version_stream(bad_version_string);
std::unique_ptr<const IdmapHeader> bad_version_header =
IdmapHeader::FromBinaryStream(bad_version_stream);
- ASSERT_THAT(bad_version_header, NotNull());
- ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion());
- ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
- target_crc, overlay_crc, policies,
- /* enforce_overlayable */ true));
+ ASSERT_EQ(nullptr, bad_version_header);
// target crc: bytes (0x8, 0xb)
std::string bad_target_crc_string(stream.str());
@@ -457,7 +467,7 @@
IdmapHeader::FromBinaryStream(bad_target_crc_stream);
ASSERT_THAT(bad_target_crc_header, NotNull());
ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
- ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
+ ASSERT_FALSE(bad_target_crc_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
target_crc, overlay_crc, policies,
/* enforce_overlayable */ true));
@@ -472,7 +482,7 @@
IdmapHeader::FromBinaryStream(bad_overlay_crc_stream);
ASSERT_THAT(bad_overlay_crc_header, NotNull());
ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
- ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
+ ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
target_crc, overlay_crc, policies,
/* enforce_overlayable */ true));
@@ -511,7 +521,7 @@
IdmapHeader::FromBinaryStream(bad_target_path_stream);
ASSERT_THAT(bad_target_path_header, NotNull());
ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
- ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
+ ASSERT_FALSE(bad_target_path_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
target_crc, overlay_crc, policies,
/* enforce_overlayable */ true));
@@ -527,7 +537,7 @@
target_crc, overlay_crc, policies,
/* enforce_overlayable */ true));
- // overlay path: bytes (0x3c, 0x47)
+ // overlay name: bytes (0x3c, 0x47)
std::string bad_overlay_name_string(stream.str());
bad_overlay_name_string[0x3c] = '\0';
std::stringstream bad_overlay_name_stream(bad_overlay_name_string);
@@ -538,8 +548,6 @@
ASSERT_FALSE(bad_overlay_name_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
target_crc, overlay_crc, policies,
/* enforce_overlayable */ true));
-
- // overlay name: bytes (0x2c, 0x37)
}
class TestVisitor : public Visitor {
diff --git a/config/hiddenapi-temp-blocklist.txt b/config/hiddenapi-max-target-r-loprio.txt
similarity index 100%
rename from config/hiddenapi-temp-blocklist.txt
rename to config/hiddenapi-max-target-r-loprio.txt
diff --git a/core/api/current.txt b/core/api/current.txt
index 5a020d4..1eeb927 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -393,6 +393,7 @@
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844039; // 0x1010507
+ field public static final int canPauseRecording = 16844314; // 0x101061a
field public static final int canPerformGestures = 16844045; // 0x101050d
field public static final int canRecord = 16844060; // 0x101051c
field @Deprecated public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
@@ -1054,9 +1055,11 @@
field public static final int parentActivityName = 16843687; // 0x10103a7
field @Deprecated public static final int password = 16843100; // 0x101015c
field public static final int path = 16842794; // 0x101002a
+ field public static final int pathAdvancedPattern = 16844319; // 0x101061f
field public static final int pathData = 16843781; // 0x1010405
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
+ field public static final int pathSuffix = 16844317; // 0x101061d
field public static final int patternPathData = 16843978; // 0x10104ca
field public static final int permission = 16842758; // 0x1010006
field public static final int permissionFlags = 16843719; // 0x10103c7
@@ -1149,7 +1152,7 @@
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
- field public static final int requireDeviceScreenOn = 16844315; // 0x101061b
+ field public static final int requireDeviceScreenOn = 16844316; // 0x101061c
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -1290,8 +1293,10 @@
field public static final int spotShadowAlpha = 16843967; // 0x10104bf
field public static final int src = 16843033; // 0x1010119
field public static final int ssp = 16843747; // 0x10103e3
+ field public static final int sspAdvancedPattern = 16844320; // 0x1010620
field public static final int sspPattern = 16843749; // 0x10103e5
field public static final int sspPrefix = 16843748; // 0x10103e4
+ field public static final int sspSuffix = 16844318; // 0x101061e
field public static final int stackFromBottom = 16843005; // 0x10100fd
field public static final int stackViewStyle = 16843838; // 0x101043e
field public static final int starStyle = 16842882; // 0x1010082
@@ -1686,6 +1691,30 @@
field @Deprecated public static final int secondary_text_dark_nodisable = 17170438; // 0x1060006
field @Deprecated public static final int secondary_text_light = 17170439; // 0x1060007
field @Deprecated public static final int secondary_text_light_nodisable = 17170440; // 0x1060008
+ field public static final int system_accent_0 = 17170473; // 0x1060029
+ field public static final int system_accent_100 = 17170475; // 0x106002b
+ field public static final int system_accent_1000 = 17170484; // 0x1060034
+ field public static final int system_accent_200 = 17170476; // 0x106002c
+ field public static final int system_accent_300 = 17170477; // 0x106002d
+ field public static final int system_accent_400 = 17170478; // 0x106002e
+ field public static final int system_accent_50 = 17170474; // 0x106002a
+ field public static final int system_accent_500 = 17170479; // 0x106002f
+ field public static final int system_accent_600 = 17170480; // 0x1060030
+ field public static final int system_accent_700 = 17170481; // 0x1060031
+ field public static final int system_accent_800 = 17170482; // 0x1060032
+ field public static final int system_accent_900 = 17170483; // 0x1060033
+ field public static final int system_main_0 = 17170461; // 0x106001d
+ field public static final int system_main_100 = 17170463; // 0x106001f
+ field public static final int system_main_1000 = 17170472; // 0x1060028
+ field public static final int system_main_200 = 17170464; // 0x1060020
+ field public static final int system_main_300 = 17170465; // 0x1060021
+ field public static final int system_main_400 = 17170466; // 0x1060022
+ field public static final int system_main_50 = 17170462; // 0x106001e
+ field public static final int system_main_500 = 17170467; // 0x1060023
+ field public static final int system_main_600 = 17170468; // 0x1060024
+ field public static final int system_main_700 = 17170469; // 0x1060025
+ field public static final int system_main_800 = 17170470; // 0x1060026
+ field public static final int system_main_900 = 17170471; // 0x1060027
field public static final int tab_indicator_text = 17170441; // 0x1060009
field @Deprecated public static final int tertiary_text_dark = 17170448; // 0x1060010
field @Deprecated public static final int tertiary_text_light = 17170449; // 0x1060011
@@ -6731,7 +6760,7 @@
method public android.content.Intent getCropAndSetWallpaperIntent(android.net.Uri);
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
- method public android.graphics.drawable.Drawable getDrawable();
+ method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable getDrawable();
method @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
method @Nullable public android.app.WallpaperColors getWallpaperColors(int);
@@ -10321,6 +10350,7 @@
field public static final String BIOMETRIC_SERVICE = "biometric";
field public static final String BLOB_STORE_SERVICE = "blob_store";
field public static final String BLUETOOTH_SERVICE = "bluetooth";
+ field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CAMERA_SERVICE = "camera";
field public static final String CAPTIONING_SERVICE = "captioning";
field public static final String CARRIER_CONFIG_SERVICE = "carrier_config";
@@ -10729,7 +10759,7 @@
field public static final String ACTION_CAMERA_BUTTON = "android.intent.action.CAMERA_BUTTON";
field public static final String ACTION_CARRIER_SETUP = "android.intent.action.CARRIER_SETUP";
field public static final String ACTION_CHOOSER = "android.intent.action.CHOOSER";
- field public static final String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
+ field @Deprecated @RequiresPermission("android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS") public static final String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
field public static final String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";
field public static final String ACTION_CREATE_DOCUMENT = "android.intent.action.CREATE_DOCUMENT";
field public static final String ACTION_CREATE_REMINDER = "android.intent.action.CREATE_REMINDER";
@@ -15514,7 +15544,6 @@
ctor public Point(int, int);
ctor public Point(@NonNull android.graphics.Point);
method public int describeContents();
- method public final void dump(@NonNull java.io.PrintWriter);
method public final boolean equals(int, int);
method public final void negate();
method public final void offset(int, int);
@@ -19911,6 +19940,7 @@
field public static final int FLAG_REMOVE_SOUND_AND_VIBRATE = 8; // 0x8
field public static final int FLAG_SHOW_UI = 1; // 0x1
field public static final int FLAG_VIBRATE = 16; // 0x10
+ field public static final int FX_BACK = 10; // 0xa
field public static final int FX_FOCUS_NAVIGATION_DOWN = 2; // 0x2
field public static final int FX_FOCUS_NAVIGATION_LEFT = 3; // 0x3
field public static final int FX_FOCUS_NAVIGATION_RIGHT = 4; // 0x4
@@ -24722,6 +24752,7 @@
}
public final class TvInputInfo implements android.os.Parcelable {
+ method public boolean canPauseRecording();
method public boolean canRecord();
method @Deprecated public android.content.Intent createSettingsIntent();
method public android.content.Intent createSetupIntent();
@@ -24755,6 +24786,7 @@
public static final class TvInputInfo.Builder {
ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
method public android.media.tv.TvInputInfo build();
+ method @NonNull public android.media.tv.TvInputInfo.Builder setCanPauseRecording(boolean);
method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
method public android.media.tv.TvInputInfo.Builder setExtras(android.os.Bundle);
method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -24846,7 +24878,9 @@
method public void notifyRecordingStopped(android.net.Uri);
method public void notifyTuned(android.net.Uri);
method public void onAppPrivateCommand(@NonNull String, android.os.Bundle);
+ method public void onPauseRecording(@NonNull android.os.Bundle);
method public abstract void onRelease();
+ method public void onResumeRecording(@NonNull android.os.Bundle);
method public abstract void onStartRecording(@Nullable android.net.Uri);
method public void onStartRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
method public abstract void onStopRecording();
@@ -24896,7 +24930,11 @@
public class TvRecordingClient {
ctor public TvRecordingClient(android.content.Context, String, @NonNull android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler);
+ method public void pauseRecording();
+ method public void pauseRecording(@NonNull android.os.Bundle);
method public void release();
+ method public void resumeRecording();
+ method public void resumeRecording(@NonNull android.os.Bundle);
method public void sendAppPrivateCommand(@NonNull String, android.os.Bundle);
method public void startRecording(@Nullable android.net.Uri);
method public void startRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
@@ -30044,6 +30082,24 @@
method public boolean unlinkToDeath(@NonNull android.os.IBinder.DeathRecipient, int);
}
+ public final class BugreportManager {
+ method public void cancelBugreport();
+ method public void startConnectivityBugreport(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
+ }
+
+ public abstract static class BugreportManager.BugreportCallback {
+ ctor public BugreportManager.BugreportCallback();
+ method public void onEarlyReportFinished();
+ method public void onError(int);
+ method public void onFinished();
+ method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
+ field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
+ field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
+ field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
+ field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
+ field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
+ }
+
public class Build {
ctor public Build();
method @NonNull public static java.util.List<android.os.Build.Partition> getFingerprintedPartitions();
@@ -30942,6 +30998,7 @@
field public static final int PATTERN_LITERAL = 0; // 0x0
field public static final int PATTERN_PREFIX = 1; // 0x1
field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
+ field public static final int PATTERN_SUFFIX = 4; // 0x4
}
public final class PersistableBundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -34432,6 +34489,7 @@
field public static final String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
field public static final String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
field public static final String ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION = "android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION";
+ field public static final String ACTION_MANAGE_ALL_SUBSCRIPTIONS_SETTINGS = "android.settings.MANAGE_ALL_SUBSCRIPTIONS_SETTINGS";
field public static final String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
field public static final String ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION = "android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION";
field public static final String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
@@ -39725,6 +39783,7 @@
field public static final int BAND_25 = 25; // 0x19
field public static final int BAND_257 = 257; // 0x101
field public static final int BAND_258 = 258; // 0x102
+ field public static final int BAND_26 = 26; // 0x1a
field public static final int BAND_260 = 260; // 0x104
field public static final int BAND_261 = 261; // 0x105
field public static final int BAND_28 = 28; // 0x1c
@@ -39736,10 +39795,12 @@
field public static final int BAND_39 = 39; // 0x27
field public static final int BAND_40 = 40; // 0x28
field public static final int BAND_41 = 41; // 0x29
+ field public static final int BAND_46 = 46; // 0x2e
field public static final int BAND_48 = 48; // 0x30
field public static final int BAND_5 = 5; // 0x5
field public static final int BAND_50 = 50; // 0x32
field public static final int BAND_51 = 51; // 0x33
+ field public static final int BAND_53 = 53; // 0x35
field public static final int BAND_65 = 65; // 0x41
field public static final int BAND_66 = 66; // 0x42
field public static final int BAND_7 = 7; // 0x7
@@ -39765,6 +39826,7 @@
field public static final int BAND_93 = 93; // 0x5d
field public static final int BAND_94 = 94; // 0x5e
field public static final int BAND_95 = 95; // 0x5f
+ field public static final int BAND_96 = 96; // 0x60
}
public static final class AccessNetworkConstants.UtranBand {
@@ -40143,6 +40205,11 @@
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
}
+ public static final class CarrierConfigManager.ImsServiceEntitlement {
+ field public static final String KEY_AES_URL_STRING = "imsserviceentitlement.aes_url_string";
+ field public static final String KEY_PREFIX = "imsserviceentitlement.";
+ }
+
public static final class CarrierConfigManager.Iwlan {
field public static final int AUTHENTICATION_METHOD_CERT = 1; // 0x1
field public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0; // 0x0
@@ -41080,12 +41147,13 @@
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
method public static void addTtsSpan(android.text.Spannable, int, int);
+ method public static boolean areSamePhoneNumber(@NonNull String, @NonNull String, @NonNull String);
method @Deprecated public static String calledPartyBCDFragmentToString(byte[], int, int);
method public static String calledPartyBCDFragmentToString(byte[], int, int, int);
method @Deprecated public static String calledPartyBCDToString(byte[], int, int);
method public static String calledPartyBCDToString(byte[], int, int, int);
- method public static boolean compare(String, String);
- method public static boolean compare(android.content.Context, String, String);
+ method @Deprecated public static boolean compare(String, String);
+ method @Deprecated public static boolean compare(android.content.Context, String, String);
method public static String convertKeypadLettersToDigits(String);
method public static android.text.style.TtsSpan createTtsSpan(String);
method public static CharSequence createTtsSpannable(CharSequence);
@@ -41270,17 +41338,27 @@
public final class PhysicalChannelConfig implements android.os.Parcelable {
method public int describeContents();
- method public int getCellBandwidthDownlink();
- method public int getChannelNumber();
+ method @IntRange(from=1, to=261) public int getBand();
+ method @IntRange(from=1) public int getCellBandwidthDownlinkKhz();
+ method @IntRange(from=1) public int getCellBandwidthUplinkKhz();
+ method @Deprecated public int getChannelNumber();
method public int getConnectionStatus();
+ method @IntRange(from=0) public int getDownlinkChannelNumber();
+ method @IntRange(from=0) public int getDownlinkFrequencyKhz();
method public int getNetworkType();
method @IntRange(from=0, to=1007) public int getPhysicalCellId();
+ method @IntRange(from=0) public int getUplinkChannelNumber();
+ method @IntRange(from=0) public int getUplinkFrequencyKhz();
method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int BAND_UNKNOWN = 0; // 0x0
+ field public static final int CELL_BANDWIDTH_UNKNOWN = 0; // 0x0
field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff
field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR;
+ field public static final int FREQUENCY_UNKNOWN = -1; // 0xffffffff
+ field public static final int PHYSICAL_CELL_ID_MAXIMUM_VALUE = 1007; // 0x3ef
field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff
}
@@ -41363,6 +41441,32 @@
field public static final int INVALID = 2147483647; // 0x7fffffff
}
+ public final class SignalThresholdInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getRadioAccessNetworkType();
+ method public int getSignalMeasurementType();
+ method @NonNull public int[] getThresholds();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SignalThresholdInfo> CREATOR;
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSCP = 2; // 0x2
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSRP = 3; // 0x3
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4; // 0x4
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSSI = 1; // 0x1
+ field public static final int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5; // 0x5
+ field public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6; // 0x6
+ field public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7; // 0x7
+ field public static final int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8; // 0x8
+ field public static final int SIGNAL_MEASUREMENT_TYPE_UNKNOWN = 0; // 0x0
+ }
+
+ public static final class SignalThresholdInfo.Builder {
+ ctor public SignalThresholdInfo.Builder();
+ method @NonNull public android.telephony.SignalThresholdInfo build();
+ method @NonNull public android.telephony.SignalThresholdInfo.Builder setRadioAccessNetworkType(int);
+ method @NonNull public android.telephony.SignalThresholdInfo.Builder setSignalMeasurementType(int);
+ method @NonNull public android.telephony.SignalThresholdInfo.Builder setThresholds(@NonNull int[]);
+ }
+
public final class SmsManager {
method public String createAppSpecificSmsToken(android.app.PendingIntent);
method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
@@ -41820,8 +41924,8 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int);
method public void unregisterPhoneStateListener(@NonNull android.telephony.PhoneStateListener);
method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
- method public void uploadCallComposerPicture(@NonNull java.nio.file.Path, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.ParcelUuid,android.telephony.TelephonyManager.CallComposerException>);
- method public void uploadCallComposerPicture(@NonNull java.io.InputStream, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.ParcelUuid,android.telephony.TelephonyManager.CallComposerException>);
+ method public void uploadCallComposerPicture(@NonNull java.nio.file.Path, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.ParcelUuid,android.telephony.TelephonyManager.CallComposerException>);
+ method public void uploadCallComposerPicture(@NonNull java.io.InputStream, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.ParcelUuid,android.telephony.TelephonyManager.CallComposerException>);
field public static final String ACTION_CARRIER_MESSAGING_CLIENT_SERVICE = "android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE";
field public static final String ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE = "android.telephony.action.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE";
field public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE = "android.telephony.action.CARRIER_SIGNAL_PCO_VALUE";
@@ -41847,6 +41951,7 @@
field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
field public static final int CALL_COMPOSER_STATUS_OFF = 0; // 0x0
field public static final int CALL_COMPOSER_STATUS_ON = 1; // 0x1
+ field public static final int CALL_COMPOSER_STATUS_ON_NO_PICTURES = 2; // 0x2
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -41972,6 +42077,7 @@
field public static final int ERROR_FILE_TOO_LARGE = 2; // 0x2
field public static final int ERROR_INPUT_CLOSED = 4; // 0x4
field public static final int ERROR_IO_EXCEPTION = 5; // 0x5
+ field public static final int ERROR_NETWORK_UNAVAILABLE = 6; // 0x6
field public static final int ERROR_REMOTE_END_CLOSED = 1; // 0x1
field public static final int ERROR_UNKNOWN = 0; // 0x0
}
@@ -42206,6 +42312,14 @@
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.euicc.DownloadableSubscription> CREATOR;
}
+ public static final class DownloadableSubscription.Builder {
+ ctor public DownloadableSubscription.Builder(@NonNull android.telephony.euicc.DownloadableSubscription);
+ ctor public DownloadableSubscription.Builder(@NonNull String);
+ method @NonNull public android.telephony.euicc.DownloadableSubscription build();
+ method @NonNull public android.telephony.euicc.DownloadableSubscription.Builder setConfirmationCode(@NonNull String);
+ method @NonNull public android.telephony.euicc.DownloadableSubscription.Builder setEncodedActivationCode(@NonNull String);
+ }
+
public final class EuiccInfo implements android.os.Parcelable {
ctor public EuiccInfo(@Nullable String);
method public int describeContents();
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index ef6c8b7..bf92b34 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -108,7 +108,7 @@
}
public final class MediaSessionManager {
- method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, int, @Nullable android.os.Handler);
+ method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, @NonNull android.os.UserHandle, @Nullable android.os.Handler);
method public void dispatchMediaKeyEvent(@NonNull android.view.KeyEvent);
method public void dispatchMediaKeyEvent(@NonNull android.view.KeyEvent, boolean);
method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent);
@@ -116,7 +116,7 @@
method public void dispatchVolumeKeyEvent(@NonNull android.view.KeyEvent, int, boolean);
method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.view.KeyEvent, int);
method public void dispatchVolumeKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
- method @NonNull public java.util.List<android.media.session.MediaController> getActiveSessionsForUser(@Nullable android.content.ComponentName, int);
+ method @NonNull public java.util.List<android.media.session.MediaController> getActiveSessionsForUser(@Nullable android.content.ComponentName, @NonNull android.os.UserHandle);
method public void registerRemoteSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.session.MediaSessionManager.RemoteSessionCallback);
method public void unregisterRemoteSessionCallback(@NonNull android.media.session.MediaSessionManager.RemoteSessionCallback);
field public static final int RESULT_MEDIA_KEY_HANDLED = 1; // 0x1
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 81f62e1..eab4d64 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -241,6 +241,7 @@
field public static final String SUBSTITUTE_NOTIFICATION_APP_NAME = "android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME";
field public static final String SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON = "android.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
+ field public static final String SYSTEM_APPLICATION_OVERLAY = "android.permission.SYSTEM_APPLICATION_OVERLAY";
field public static final String SYSTEM_CAMERA = "android.permission.SYSTEM_CAMERA";
field public static final String TETHER_PRIVILEGED = "android.permission.TETHER_PRIVILEGED";
field public static final String TOGGLE_AUTOMOTIVE_PROJECTION = "android.permission.TOGGLE_AUTOMOTIVE_PROJECTION";
@@ -892,6 +893,8 @@
field public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_ICON_URI";
field public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL";
field public static final String EXTRA_PROVISIONING_ORGANIZATION_NAME = "android.app.extra.PROVISIONING_ORGANIZATION_NAME";
+ field public static final String EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE = "android.app.extra.PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE";
+ field public static final String EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER = "android.app.extra.PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER";
field public static final String EXTRA_PROVISIONING_SUPPORTED_MODES = "android.app.extra.PROVISIONING_SUPPORTED_MODES";
field public static final String EXTRA_PROVISIONING_SUPPORT_URL = "android.app.extra.PROVISIONING_SUPPORT_URL";
field public static final String EXTRA_PROVISIONING_TRIGGER = "android.app.extra.PROVISIONING_TRIGGER";
@@ -1921,7 +1924,6 @@
field public static final String BATTERY_STATS_SERVICE = "batterystats";
field public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
field public static final int BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND = 262144; // 0x40000
- field public static final String BUGREPORT_SERVICE = "bugreport";
field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
field public static final String CONTEXTHUB_SERVICE = "contexthub";
field public static final String ETHERNET_SERVICE = "ethernet";
@@ -2737,21 +2739,42 @@
}
public final class HdmiControlManager {
+ method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void addHdmiCecEnabledChangeListener(@NonNull android.hardware.hdmi.HdmiControlManager.CecSettingChangeListener);
+ method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void addHdmiCecEnabledChangeListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.hdmi.HdmiControlManager.CecSettingChangeListener);
method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void addHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void addHotplugEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
+ method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public java.util.List<java.lang.Integer> getAllowedCecSettingIntValues(@NonNull String);
+ method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public java.util.List<java.lang.String> getAllowedCecSettingStringValues(@NonNull String);
method @Nullable public android.hardware.hdmi.HdmiClient getClient(int);
method @NonNull public java.util.List<android.hardware.hdmi.HdmiDeviceInfo> getConnectedDevices();
+ method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getHdmiCecEnabled();
+ method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getHdmiCecVersion();
method public int getPhysicalAddress();
method @Nullable public android.hardware.hdmi.HdmiPlaybackClient getPlaybackClient();
+ method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public String getPowerControlMode();
+ method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public String getPowerStateChangeOnActiveSourceLost();
method @Nullable public android.hardware.hdmi.HdmiSwitchClient getSwitchClient();
+ method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public int getSystemAudioModeMuting();
method @Nullable public android.hardware.hdmi.HdmiTvClient getTvClient();
+ method @NonNull @RequiresPermission(android.Manifest.permission.HDMI_CEC) public java.util.List<java.lang.String> getUserCecSettings();
method public boolean isDeviceConnected(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
method public void powerOffDevice(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
+ method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void removeHdmiCecEnabledChangeListener(@NonNull android.hardware.hdmi.HdmiControlManager.CecSettingChangeListener);
method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void removeHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
method public void setActiveSource(@NonNull android.hardware.hdmi.HdmiDeviceInfo);
+ method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setHdmiCecEnabled(@NonNull int);
+ method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setHdmiCecVersion(@NonNull int);
+ method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setPowerControlMode(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setPowerStateChangeOnActiveSourceLost(@NonNull String);
method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setStandbyMode(boolean);
+ method @RequiresPermission(android.Manifest.permission.HDMI_CEC) public void setSystemAudioModeMuting(@NonNull int);
field public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
field public static final int AVR_VOLUME_MUTED = 101; // 0x65
+ field public static final String CEC_SETTING_NAME_HDMI_CEC_ENABLED = "hdmi_cec_enabled";
+ field public static final String CEC_SETTING_NAME_HDMI_CEC_VERSION = "hdmi_cec_version";
+ field public static final String CEC_SETTING_NAME_POWER_CONTROL_MODE = "send_standby_on_sleep";
+ field public static final String CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST = "power_state_change_on_active_source_lost";
+ field public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING = "system_audio_mode_muting";
field public static final int CLEAR_TIMER_STATUS_CEC_DISABLE = 162; // 0xa2
field public static final int CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION = 160; // 0xa0
field public static final int CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE = 161; // 0xa1
@@ -2768,6 +2791,10 @@
field public static final int DEVICE_EVENT_UPDATE_DEVICE = 3; // 0x3
field public static final String EXTRA_MESSAGE_EXTRA_PARAM1 = "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1";
field public static final String EXTRA_MESSAGE_ID = "android.hardware.hdmi.extra.MESSAGE_ID";
+ field public static final int HDMI_CEC_CONTROL_DISABLED = 0; // 0x0
+ field public static final int HDMI_CEC_CONTROL_ENABLED = 1; // 0x1
+ field public static final int HDMI_CEC_VERSION_1_4_B = 5; // 0x5
+ field public static final int HDMI_CEC_VERSION_2_0 = 6; // 0x6
field public static final int ONE_TOUCH_RECORD_ALREADY_RECORDING = 18; // 0x12
field public static final int ONE_TOUCH_RECORD_CEC_DISABLED = 51; // 0x33
field public static final int ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION = 49; // 0x31
@@ -2798,6 +2825,11 @@
field public static final int ONE_TOUCH_RECORD_UNSUPPORTED_CA = 11; // 0xb
field public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1; // 0x1
field public static final int OSD_MESSAGE_AVR_VOLUME_CHANGED = 2; // 0x2
+ field public static final String POWER_CONTROL_MODE_BROADCAST = "broadcast";
+ field public static final String POWER_CONTROL_MODE_NONE = "none";
+ field public static final String POWER_CONTROL_MODE_TV = "to_tv";
+ field public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE = "none";
+ field public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW = "standby_now";
field public static final int POWER_STATUS_ON = 0; // 0x0
field public static final int POWER_STATUS_STANDBY = 1; // 0x1
field public static final int POWER_STATUS_TRANSIENT_TO_ON = 2; // 0x2
@@ -2811,6 +2843,8 @@
field public static final int RESULT_SUCCESS = 0; // 0x0
field public static final int RESULT_TARGET_NOT_AVAILABLE = 3; // 0x3
field public static final int RESULT_TIMEOUT = 1; // 0x1
+ field public static final int SYSTEM_AUDIO_MODE_MUTING_DISABLED = 0; // 0x0
+ field public static final int SYSTEM_AUDIO_MODE_MUTING_ENABLED = 1; // 0x1
field public static final int TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED = 3; // 0x3
field public static final int TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION = 1; // 0x1
field public static final int TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE = 2; // 0x2
@@ -2838,6 +2872,10 @@
field public static final int TIMER_STATUS_PROGRAMMED_INFO_NO_MEDIA_INFO = 10; // 0xa
}
+ public static interface HdmiControlManager.CecSettingChangeListener {
+ method public void onChange(@NonNull String);
+ }
+
@IntDef({android.hardware.hdmi.HdmiControlManager.RESULT_SUCCESS, android.hardware.hdmi.HdmiControlManager.RESULT_TIMEOUT, android.hardware.hdmi.HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE, android.hardware.hdmi.HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE, android.hardware.hdmi.HdmiControlManager.RESULT_ALREADY_IN_PROGRESS, android.hardware.hdmi.HdmiControlManager.RESULT_EXCEPTION, android.hardware.hdmi.HdmiControlManager.RESULT_INCORRECT_MODE, android.hardware.hdmi.HdmiControlManager.RESULT_COMMUNICATION_FAILED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public static @interface HdmiControlManager.ControlCallbackResult {
}
@@ -3946,6 +3984,25 @@
method public void onLocationBatch(java.util.List<android.location.Location>);
}
+ public final class CorrelationVector implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=0) public int getFrequencyOffsetMetersPerSecond();
+ method @NonNull public int[] getMagnitude();
+ method @FloatRange(from=0.0f) public double getSamplingStartMeters();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getSamplingWidthMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.CorrelationVector> CREATOR;
+ }
+
+ public static final class CorrelationVector.Builder {
+ ctor public CorrelationVector.Builder();
+ method @NonNull public android.location.CorrelationVector build();
+ method @NonNull public android.location.CorrelationVector.Builder setFrequencyOffsetMetersPerSecond(@IntRange(from=0) int);
+ method @NonNull public android.location.CorrelationVector.Builder setMagnitude(@NonNull int[]);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingStartMeters(@FloatRange(from=0.0f) double);
+ method @NonNull public android.location.CorrelationVector.Builder setSamplingWidthMeters(@FloatRange(from=0.0f, fromInclusive=false) double);
+ }
+
public final class GnssCapabilities implements android.os.Parcelable {
method public boolean hasGeofencing();
method public boolean hasLowPowerMode();
@@ -3954,9 +4011,11 @@
method public boolean hasMeasurementCorrectionsLosSats();
method @Deprecated public boolean hasMeasurementCorrectionsReflectingPane();
method public boolean hasMeasurementCorrectionsReflectingPlane();
+ method public boolean hasMeasurementCorrelationVectors();
method @Deprecated public boolean hasNavMessages();
method @Deprecated public boolean hasSatelliteBlacklist();
method public boolean hasSatelliteBlocklist();
+ method public boolean hasSatellitePvt();
}
public static final class GnssCapabilities.Builder {
@@ -3966,7 +4025,16 @@
method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsExcessPathLength(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsLosSats(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrectionsReflectingPlane(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasMeasurementCorrelationVectors(boolean);
method @NonNull public android.location.GnssCapabilities.Builder setHasSatelliteBlocklist(boolean);
+ method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
+ }
+
+ public final class GnssMeasurement implements android.os.Parcelable {
+ method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
+ method @Nullable public android.location.SatellitePvt getSatellitePvt();
+ method public boolean hasCorrelationVectors();
+ method public boolean hasSatellitePvt();
}
public final class GnssMeasurementCorrections implements android.os.Parcelable {
@@ -3999,6 +4067,14 @@
method @NonNull public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(@FloatRange(from=0.0f) double);
}
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method public boolean isCorrelationVectorOutputsEnabled();
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setCorrelationVectorOutputsEnabled(boolean);
+ }
+
public final class GnssReflectingPlane implements android.os.Parcelable {
method public int describeContents();
method @FloatRange(from=-1000.0F, to=10000.0f) public double getAltitudeMeters();
@@ -4381,6 +4457,59 @@
method @NonNull public static android.location.LocationResult wrap(@NonNull android.location.Location);
}
+ public final class SatellitePvt implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.location.SatellitePvt.ClockInfo getClockInfo();
+ method @FloatRange public double getIonoDelayMeters();
+ method @NonNull public android.location.SatellitePvt.PositionEcef getPositionEcef();
+ method @FloatRange public double getTropoDelayMeters();
+ method @NonNull public android.location.SatellitePvt.VelocityEcef getVelocityEcef();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt> CREATOR;
+ }
+
+ public static final class SatellitePvt.Builder {
+ ctor public SatellitePvt.Builder();
+ method @NonNull public android.location.SatellitePvt build();
+ method @NonNull public android.location.SatellitePvt.Builder setClockInfo(@NonNull android.location.SatellitePvt.ClockInfo);
+ method @NonNull public android.location.SatellitePvt.Builder setIonoDelayMeters(@FloatRange double);
+ method @NonNull public android.location.SatellitePvt.Builder setPositionEcef(@NonNull android.location.SatellitePvt.PositionEcef);
+ method @NonNull public android.location.SatellitePvt.Builder setTropoDelayMeters(@FloatRange double);
+ method @NonNull public android.location.SatellitePvt.Builder setVelocityEcef(@NonNull android.location.SatellitePvt.VelocityEcef);
+ }
+
+ public static final class SatellitePvt.ClockInfo implements android.os.Parcelable {
+ ctor public SatellitePvt.ClockInfo(double, double, double);
+ method public int describeContents();
+ method @FloatRange public double getClockDriftMetersPerSecond();
+ method @FloatRange public double getHardwareCodeBiasMeters();
+ method @FloatRange public double getTimeCorrectionMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.ClockInfo> CREATOR;
+ }
+
+ public static final class SatellitePvt.PositionEcef implements android.os.Parcelable {
+ ctor public SatellitePvt.PositionEcef(double, double, double, double);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getUreMeters();
+ method @FloatRange public double getXMeters();
+ method @FloatRange public double getYMeters();
+ method @FloatRange public double getZMeters();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.PositionEcef> CREATOR;
+ }
+
+ public static final class SatellitePvt.VelocityEcef implements android.os.Parcelable {
+ ctor public SatellitePvt.VelocityEcef(double, double, double, double);
+ method public int describeContents();
+ method @FloatRange(from=0.0f, fromInclusive=false) public double getUreRateMetersPerSecond();
+ method @FloatRange public double getXMetersPerSecond();
+ method @FloatRange public double getYMetersPerSecond();
+ method @FloatRange public double getZMetersPerSecond();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.SatellitePvt.VelocityEcef> CREATOR;
+ }
+
}
package android.location.provider {
@@ -5222,9 +5351,9 @@
method public int disconnectFrontendToCiCam(int);
method public int getAvSyncHwId(@NonNull android.media.tv.tuner.filter.Filter);
method public long getAvSyncTime(int);
+ method @Nullable public java.util.List<android.media.tv.tuner.frontend.FrontendInfo> getAvailableFrontendInfos();
method @Nullable public android.media.tv.tuner.DemuxCapabilities getDemuxCapabilities();
method @Nullable public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
- method @Nullable public java.util.List<android.media.tv.tuner.frontend.FrontendInfo> getFrontendInfoList();
method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler();
method @Nullable public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
@@ -7724,24 +7853,10 @@
}
public final class BugreportManager {
- method @RequiresPermission(android.Manifest.permission.DUMP) public void cancelBugreport();
method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence);
method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
}
- public abstract static class BugreportManager.BugreportCallback {
- ctor public BugreportManager.BugreportCallback();
- method public void onEarlyReportFinished();
- method public void onError(int);
- method public void onFinished();
- method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
- field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
- field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
- field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
- field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
- field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
- }
-
public final class BugreportParams {
ctor public BugreportParams(int);
method public int getMode();
@@ -8200,11 +8315,13 @@
}
public class UserManager {
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean canHaveRestrictedProfile();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearSeedAccountData();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle createProfile(@NonNull String, @NonNull String, @NonNull java.util.Set<java.lang.String>) throws android.os.UserManager.UserOperationException;
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getAllProfiles();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getEnabledProfiles();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle getRestrictedProfileParent();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountName();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountType();
@@ -11765,12 +11882,8 @@
public static final class DownloadableSubscription.Builder {
ctor public DownloadableSubscription.Builder();
- ctor public DownloadableSubscription.Builder(android.telephony.euicc.DownloadableSubscription);
- method public android.telephony.euicc.DownloadableSubscription build();
- method public android.telephony.euicc.DownloadableSubscription.Builder setAccessRules(java.util.List<android.telephony.UiccAccessRule>);
- method public android.telephony.euicc.DownloadableSubscription.Builder setCarrierName(String);
- method public android.telephony.euicc.DownloadableSubscription.Builder setConfirmationCode(String);
- method public android.telephony.euicc.DownloadableSubscription.Builder setEncodedActivationCode(String);
+ method @NonNull public android.telephony.euicc.DownloadableSubscription.Builder setAccessRules(@NonNull java.util.List<android.telephony.UiccAccessRule>);
+ method @NonNull public android.telephony.euicc.DownloadableSubscription.Builder setCarrierName(@NonNull String);
}
public class EuiccCardManager {
@@ -13245,9 +13358,10 @@
method public final void setUserActivityTimeout(long);
field @RequiresPermission(android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS) public static final int SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS = 524288; // 0x80000
field @RequiresPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) public static final int SYSTEM_FLAG_SHOW_FOR_ALL_USERS = 16; // 0x10
+ field @RequiresPermission(android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY) public static final int SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY = 8; // 0x8
}
- @IntDef(flag=true, prefix={"SYSTEM_FLAG_"}, value={android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowManager.LayoutParams.SystemFlags {
+ @IntDef(flag=true, prefix={"SYSTEM_FLAG_"}, value={android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS, android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface WindowManager.LayoutParams.SystemFlags {
}
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 1422561..775ded7 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -385,18 +385,35 @@
method @NonNull public static String operationToString(int);
method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, boolean);
field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
+ field public static final int OPERATION_CLEAR_APPLICATION_USER_DATA = 23; // 0x17
field public static final int OPERATION_CREATE_AND_MANAGE_USER = 5; // 0x5
+ field public static final int OPERATION_INSTALL_CA_CERT = 24; // 0x18
+ field public static final int OPERATION_INSTALL_KEY_PAIR = 25; // 0x19
+ field public static final int OPERATION_INSTALL_SYSTEM_UPDATE = 26; // 0x1a
field public static final int OPERATION_LOCK_NOW = 1; // 0x1
field public static final int OPERATION_LOGOUT_USER = 9; // 0x9
field public static final int OPERATION_REBOOT = 7; // 0x7
+ field public static final int OPERATION_REMOVE_ACTIVE_ADMIN = 27; // 0x1b
+ field public static final int OPERATION_REMOVE_KEY_PAIR = 28; // 0x1c
field public static final int OPERATION_REMOVE_USER = 6; // 0x6
+ field public static final int OPERATION_REQUEST_BUGREPORT = 29; // 0x1d
+ field public static final int OPERATION_SET_ALWAYS_ON_VPN_PACKAGE = 30; // 0x1e
field public static final int OPERATION_SET_APPLICATION_HIDDEN = 15; // 0xf
field public static final int OPERATION_SET_APPLICATION_RESTRICTIONS = 16; // 0x10
+ field public static final int OPERATION_SET_CAMERA_DISABLED = 31; // 0x1f
+ field public static final int OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY = 32; // 0x20
+ field public static final int OPERATION_SET_GLOBAL_PRIVATE_DNS = 33; // 0x21
field public static final int OPERATION_SET_KEEP_UNINSTALLED_PACKAGES = 17; // 0x11
field public static final int OPERATION_SET_KEYGUARD_DISABLED = 12; // 0xc
field public static final int OPERATION_SET_LOCK_TASK_FEATURES = 18; // 0x12
field public static final int OPERATION_SET_LOCK_TASK_PACKAGES = 19; // 0x13
+ field public static final int OPERATION_SET_LOGOUT_ENABLED = 34; // 0x22
+ field public static final int OPERATION_SET_MASTER_VOLUME_MUTED = 35; // 0x23
+ field public static final int OPERATION_SET_OVERRIDE_APNS_ENABLED = 36; // 0x24
field public static final int OPERATION_SET_PACKAGES_SUSPENDED = 20; // 0x14
+ field public static final int OPERATION_SET_PERMISSION_GRANT_STATE = 37; // 0x25
+ field public static final int OPERATION_SET_PERMISSION_POLICY = 38; // 0x26
+ field public static final int OPERATION_SET_RESTRICTIONS_PROVIDER = 39; // 0x27
field public static final int OPERATION_SET_STATUS_BAR_DISABLED = 13; // 0xd
field public static final int OPERATION_SET_SYSTEM_SETTING = 11; // 0xb
field public static final int OPERATION_SET_SYSTEM_UPDATE_POLICY = 14; // 0xe
@@ -406,6 +423,7 @@
field public static final int OPERATION_START_USER_IN_BACKGROUND = 3; // 0x3
field public static final int OPERATION_STOP_USER = 4; // 0x4
field public static final int OPERATION_SWITCH_USER = 2; // 0x2
+ field public static final int OPERATION_UNINSTALL_CA_CERT = 40; // 0x28
field public static final int OPERATION_WIPE_DATA = 8; // 0x8
}
@@ -449,13 +467,10 @@
package android.app.role {
- public class RoleControllerManager {
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationVisibleForRole(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
- }
-
public final class RoleManager {
method @Nullable public String getSmsRoleHolder(int);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isApplicationVisibleForRole(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void isRoleVisible(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
}
}
@@ -730,6 +745,18 @@
}
+package android.hardware {
+
+ public final class SensorPrivacyManager {
+ method public boolean isIndividualSensorPrivacyEnabled(int);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setIndividualSensorPrivacy(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setIndividualSensorPrivacyForProfileGroup(int, boolean);
+ field public static final int INDIVIDUAL_SENSOR_CAMERA = 2; // 0x2
+ field public static final int INDIVIDUAL_SENSOR_MICROPHONE = 1; // 0x1
+ }
+
+}
+
package android.hardware.biometrics {
public class BiometricManager {
@@ -929,10 +956,12 @@
method @Deprecated public void resetCarrierPhase();
method @Deprecated public void resetCarrierPhaseUncertainty();
method public void resetCodeType();
+ method public void resetCorrelationVectors();
method public void resetFullInterSignalBiasNanos();
method public void resetFullInterSignalBiasUncertaintyNanos();
method public void resetSatelliteInterSignalBiasNanos();
method public void resetSatelliteInterSignalBiasUncertaintyNanos();
+ method public void resetSatellitePvt();
method public void resetSnrInDb();
method public void set(android.location.GnssMeasurement);
method public void setAccumulatedDeltaRangeMeters(double);
@@ -947,6 +976,7 @@
method public void setCn0DbHz(double);
method public void setCodeType(@NonNull String);
method public void setConstellationType(int);
+ method public void setCorrelationVectors(@Nullable java.util.Collection<android.location.CorrelationVector>);
method public void setFullInterSignalBiasNanos(double);
method public void setFullInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
method public void setMultipathIndicator(int);
@@ -956,6 +986,7 @@
method public void setReceivedSvTimeUncertaintyNanos(long);
method public void setSatelliteInterSignalBiasNanos(double);
method public void setSatelliteInterSignalBiasUncertaintyNanos(@FloatRange(from=0.0) double);
+ method public void setSatellitePvt(@Nullable android.location.SatellitePvt);
method public void setSnrInDb(double);
method public void setState(int);
method public void setSvid(int);
@@ -1939,7 +1970,6 @@
method public static java.util.Map<java.lang.String,java.lang.String> getAllFeatureFlags();
method public static boolean isEnabled(android.content.Context, String);
method public static void setEnabled(android.content.Context, String, boolean);
- field public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
field public static final String FFLAG_OVERRIDE_PREFIX = "sys.fflag.override.";
field public static final String FFLAG_PREFIX = "sys.fflag.";
field public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index c0b4093..216d340 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -468,6 +468,8 @@
GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
+
+GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
@@ -477,6 +479,8 @@
GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
+GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
+
GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
GetterSetterNames: android.location.LocationRequest#isLocationSettingsIgnored():
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index db83813..f7f42a6 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -32,6 +32,7 @@
import android.os.IBinder;
import android.os.TransactionTooLargeException;
import android.os.WorkSource;
+import android.util.ArraySet;
import java.util.ArrayList;
import java.util.List;
@@ -97,11 +98,15 @@
public abstract void killForegroundAppsForUser(@UserIdInt int userId);
/**
- * Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions
- * such as Power Save mode.
+ * Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions
+ * such as Power Save mode.
+ * @param target
+ * @param whitelistToken
+ * @param duration temp allowlist duration in milliseconds.
+ * @param type temp allowlist type defined at {@link BroadcastOptions.TempAllowListType}
*/
public abstract void setPendingIntentWhitelistDuration(IIntentSender target,
- IBinder whitelistToken, long duration);
+ IBinder whitelistToken, long duration, int type);
/**
* Returns the flags set for a {@link PendingIntent}.
@@ -317,8 +322,17 @@
public abstract boolean isBooted();
public abstract void finishBooting();
+ /**
+ * Temp allowlist a UID for PendingIntent.
+ * @param callerPid the PID that sent the PendingIntent.
+ * @param callerUid the UID that sent the PendingIntent.
+ * @param targetUid the UID that is been temp allowlisted.
+ * @param duration temp allowlist duration in milliseconds.
+ * @param type temp allowlist type defined at {@link BroadcastOptions.TempAllowListType}
+ * @param tag
+ */
public abstract void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
- long duration, String tag);
+ long duration, int type, String tag);
public abstract int broadcastIntentInPackage(String packageName, @Nullable String featureId,
int uid, int realCallingUid, int realCallingPid, Intent intent, String resolvedType,
@@ -447,6 +461,16 @@
*/
public abstract void setDeviceOwnerUid(int uid);
+ /** Is this a profile owner app? */
+ public abstract boolean isProfileOwner(int uid);
+
+ /**
+ * Called by DevicePolicyManagerService to set the uid of the profile owner.
+ * @param profileOwnerUids The profile owner UIDs. The ownership of the array is
+ * passed to callee.
+ */
+ public abstract void setProfileOwnerUid(ArraySet<Integer> profileOwnerUids);
+
/**
* Set all associated companion app that belongs to a userId.
* @param userId
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index f541e1a..d0d5df9 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -54,6 +54,7 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
+import android.window.IRemoteTransition;
import android.window.WindowContainerToken;
import java.lang.annotation.Retention;
@@ -298,6 +299,8 @@
private static final String KEY_SPECS_FUTURE = "android:activity.specsFuture";
private static final String KEY_REMOTE_ANIMATION_ADAPTER
= "android:activity.remoteAnimationAdapter";
+ private static final String KEY_REMOTE_TRANSITION =
+ "android:activity.remoteTransition";
/**
* @see #setLaunchCookie
@@ -380,6 +383,7 @@
private IAppTransitionAnimationSpecsFuture mSpecsFuture;
private RemoteAnimationAdapter mRemoteAnimationAdapter;
private IBinder mLaunchCookie;
+ private IRemoteTransition mRemoteTransition;
/**
* Create an ActivityOptions specifying a custom animation to run when
@@ -959,6 +963,21 @@
return opts;
}
+ /**
+ * Create an {@link ActivityOptions} instance that lets the application control the entire
+ * animation using a {@link RemoteAnimationAdapter}.
+ * @hide
+ */
+ @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
+ public static ActivityOptions makeRemoteAnimation(RemoteAnimationAdapter remoteAnimationAdapter,
+ IRemoteTransition remoteTransition) {
+ final ActivityOptions opts = new ActivityOptions();
+ opts.mRemoteAnimationAdapter = remoteAnimationAdapter;
+ opts.mAnimationType = ANIM_REMOTE_ANIMATION;
+ opts.mRemoteTransition = remoteTransition;
+ return opts;
+ }
+
/** @hide */
public boolean getLaunchTaskBehind() {
return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -1064,6 +1083,8 @@
}
mRemoteAnimationAdapter = opts.getParcelable(KEY_REMOTE_ANIMATION_ADAPTER);
mLaunchCookie = opts.getBinder(KEY_LAUNCH_COOKIE);
+ mRemoteTransition = IRemoteTransition.Stub.asInterface(opts.getBinder(
+ KEY_REMOTE_TRANSITION));
}
/**
@@ -1223,6 +1244,11 @@
}
/** @hide */
+ public IRemoteTransition getRemoteTransition() {
+ return mRemoteTransition;
+ }
+
+ /** @hide */
public static ActivityOptions fromBundle(Bundle bOptions) {
return bOptions != null ? new ActivityOptions(bOptions) : null;
}
@@ -1724,6 +1750,9 @@
if (mLaunchCookie != null) {
b.putBinder(KEY_LAUNCH_COOKIE, mLaunchCookie);
}
+ if (mRemoteTransition != null) {
+ b.putBinder(KEY_REMOTE_TRANSITION, mRemoteTransition.asBinder());
+ }
return b;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2fe1711..bd437f4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2328,7 +2328,7 @@
return null;
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
public final LoadedApk getPackageInfo(ApplicationInfo ai, CompatibilityInfo compatInfo,
int flags) {
boolean includeCode = (flags&Context.CONTEXT_INCLUDE_CODE) != 0;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 20953c6..a23dd35 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -7664,8 +7664,8 @@
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
&& (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
- myUid) == PackageManager.PERMISSION_GRANTED
- || isTrustedVoiceServiceProxy(mContext, mContext.getOpPackageName(), op))) {
+ myUid) == PackageManager.PERMISSION_GRANTED || isTrustedVoiceServiceProxy(
+ mContext, mContext.getOpPackageName(), op, mContext.getUserId()))) {
collectNotedOpSync(op, proxiedAttributionTag);
}
}
@@ -7683,7 +7683,7 @@
* @hide
*/
public static boolean isTrustedVoiceServiceProxy(Context context, String packageName,
- int code) {
+ int code, int userId) {
// This is a workaround for R QPR, new API change is not allowed. We only allow the current
// voice recognizer is also the voice interactor to noteproxy op.
if (code != OP_RECORD_AUDIO) {
@@ -7695,7 +7695,7 @@
final String voiceRecognitionServicePackageName =
getComponentPackageNameFromString(voiceRecognitionComponent);
return (Objects.equals(packageName, voiceRecognitionServicePackageName))
- && isPackagePreInstalled(context, packageName);
+ && isPackagePreInstalled(context, packageName, userId);
}
private static String getComponentPackageNameFromString(String from) {
@@ -7703,10 +7703,11 @@
return componentName != null ? componentName.getPackageName() : "";
}
- private static boolean isPackagePreInstalled(Context context, String packageName) {
+ private static boolean isPackagePreInstalled(Context context, String packageName, int userId) {
try {
final PackageManager pm = context.getPackageManager();
- final ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+ final ApplicationInfo info =
+ pm.getApplicationInfoAsUser(packageName, 0, userId);
return ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
} catch (PackageManager.NameNotFoundException e) {
return false;
@@ -8069,12 +8070,15 @@
collectNotedOpForSelf(opInt, proxiedAttributionTag);
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
- && mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
- Process.myUid()) == PackageManager.PERMISSION_GRANTED) {
+ && (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
+ Process.myUid()) == PackageManager.PERMISSION_GRANTED
+ || isTrustedVoiceServiceProxy(mContext, mContext.getOpPackageName(), opInt,
+ mContext.getUserId()))) {
collectNotedOpSync(opInt, proxiedAttributionTag);
}
}
+
return mode;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 73327011..bac5025 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1795,7 +1795,6 @@
@Override
public boolean bindService(
Intent service, int flags, Executor executor, ServiceConnection conn) {
- warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, null, null, executor, getUser());
}
@@ -1996,8 +1995,7 @@
}
private static boolean isUiComponent(String name) {
- return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name)
- || WALLPAPER_SERVICE.equals(name);
+ return WINDOW_SERVICE.equals(name) || LAYOUT_INFLATER_SERVICE.equals(name);
}
@Override
diff --git a/core/java/android/app/EventLogTags.logtags b/core/java/android/app/EventLogTags.logtags
index 6296a68..d0856f4 100644
--- a/core/java/android/app/EventLogTags.logtags
+++ b/core/java/android/app/EventLogTags.logtags
@@ -10,8 +10,6 @@
# The activity's onResume has been called.
30022 wm_on_resume_called (Token|1|5),(Component Name|3),(Reason|3)
-# Attempting to stop an activity
-30048 wm_stop_activity (User|1|5),(Token|1|5),(Component Name|3)
# The activity's onStop has been called.
30049 wm_on_stop_called (Token|1|5),(Component Name|3),(Reason|3)
@@ -31,6 +29,3 @@
# The activity's onTopResumedActivityChanged(false) has been called.
30065 wm_on_top_resumed_lost_called (Token|1|5),(Component Name|3),(Reason|3)
-# An activity been add into stopping list
-30066 wm_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
-
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5fbc948..f6a06f3 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -10058,7 +10058,7 @@
* <pre class="prettyprint">
* Intent displayIntent = new Intent(context, MyDisplayActivity.class);
* PendingIntent displayPendingIntent = PendingIntent.getActivity(context,
- * 0, displayIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ * 0, displayIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
* Notification notif = new Notification.Builder(context)
* .extend(new Notification.WearableExtender()
* .setDisplayIntent(displayPendingIntent)
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index dd016a2..fe13fd4 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -31,7 +31,6 @@
import android.app.job.JobSchedulerFrameworkInitializer;
import android.app.people.PeopleManager;
import android.app.prediction.AppPredictionManager;
-import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
import android.app.search.SearchUiManager;
import android.app.slice.SliceManager;
@@ -1315,14 +1314,6 @@
return new RoleManager(ctx.getOuterContext());
}});
- registerService(Context.ROLE_CONTROLLER_SERVICE, RoleControllerManager.class,
- new CachedServiceFetcher<RoleControllerManager>() {
- @Override
- public RoleControllerManager createService(ContextImpl ctx)
- throws ServiceNotFoundException {
- return new RoleControllerManager(ctx.getOuterContext());
- }});
-
registerService(Context.DYNAMIC_SYSTEM_SERVICE, DynamicSystemManager.class,
new CachedServiceFetcher<DynamicSystemManager>() {
@Override
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index ab0901d..ac2f223 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -63,6 +63,7 @@
import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.StrictMode;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
@@ -605,7 +606,9 @@
* or {@code null} if no system wallpaper exists or if the calling application
* is not able to access the wallpaper.
*/
+ @RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
public Drawable getDrawable() {
+ assertUiContext("getDrawable");
final ColorManagementProxy cmProxy = getColorManagementProxy();
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, cmProxy);
if (bm != null) {
@@ -673,6 +676,7 @@
*/
public Drawable getBuiltInDrawable(int outWidth, int outHeight, boolean scaleToFit,
float horizontalAlignment, float verticalAlignment, @SetWallpaperFlags int which) {
+ assertUiContext("getBuiltInDrawable");
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
@@ -838,6 +842,7 @@
* null pointer if these is none.
*/
public Drawable peekDrawable() {
+ assertUiContext("peekDrawable");
final ColorManagementProxy cmProxy = getColorManagementProxy();
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, cmProxy);
if (bm != null) {
@@ -880,6 +885,7 @@
*/
@RequiresPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
public Drawable peekFastDrawable() {
+ assertUiContext("peekFastDrawable");
final ColorManagementProxy cmProxy = getColorManagementProxy();
Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false, FLAG_SYSTEM, cmProxy);
if (bm != null) {
@@ -1046,6 +1052,7 @@
*/
@UnsupportedAppUsage
public @Nullable WallpaperColors getWallpaperColors(int which, int userId) {
+ assertUiContext("getWallpaperColors");
return sGlobals.getWallpaperColors(which, userId, mContext.getDisplayId());
}
@@ -1261,6 +1268,7 @@
@RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public int setResource(@RawRes int resid, @SetWallpaperFlags int which)
throws IOException {
+ assertUiContext("setResource");
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
@@ -1581,6 +1589,7 @@
* @see #getDesiredMinimumHeight()
*/
public int getDesiredMinimumWidth() {
+ assertUiContext("getDesiredMinimumWidth");
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
@@ -1609,6 +1618,7 @@
* @see #getDesiredMinimumWidth()
*/
public int getDesiredMinimumHeight() {
+ assertUiContext("getDesiredMinimumHeight");
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
throw new RuntimeException(new DeadSystemException());
@@ -1639,6 +1649,7 @@
* @param minimumHeight Desired minimum height
*/
public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) {
+ assertUiContext("suggestDesiredDimensions");
try {
/**
* The framework makes no attempt to limit the window size
@@ -1694,6 +1705,7 @@
*/
@RequiresPermission(android.Manifest.permission.SET_WALLPAPER_HINTS)
public void setDisplayPadding(Rect padding) {
+ assertUiContext("setDisplayPadding");
try {
if (sGlobals.mService == null) {
Log.w(TAG, "WallpaperService not running");
@@ -1946,6 +1958,7 @@
*/
@RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
public void clear() throws IOException {
+ assertUiContext("clear");
setStream(openDefaultWallpaper(mContext, FLAG_SYSTEM), null, false);
}
@@ -2094,6 +2107,10 @@
return mCmProxy;
}
+ private void assertUiContext(final String methodName) {
+ StrictMode.assertUiContext(mContext, methodName);
+ }
+
/**
* A hidden class to help {@link Globals#getCurrentWallpaperLocked} handle color management.
* @hide
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7bc967f..54e1ac43 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2536,6 +2536,22 @@
"android.app.extra.PROVISIONING_SUPPORTED_MODES";
/**
+ * A boolean extra which determines whether to skip the ownership disclaimer screen during the
+ * provisioning flow. The default value is {@code false}.
+ *
+ * If the value is {@code true}, it is the responsibility of the provisioning initiator to
+ * show the relevant disclaimer.
+ *
+ * <p>This extra is only respected when provided alongside the {@link
+ * #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} intent action.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER =
+ "android.app.extra.PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER";
+
+ /**
* An {@link ArrayList} of {@link Integer} extra specifying the allowed provisioning modes.
* <p>This extra will be passed to the admin app's {@link #ACTION_GET_PROVISIONING_MODE}
* activity, whose result intent must contain {@link #EXTRA_PROVISIONING_MODE} set to one of
@@ -2564,6 +2580,30 @@
public static final int PROVISIONING_MODE_MANAGED_PROFILE_ON_PERSONAL_DEVICE = 3;
/**
+ * A {@code boolean} flag that indicates whether the provisioning flow should return before
+ * starting the admin app's {@link #ACTION_ADMIN_POLICY_COMPLIANCE} handler. The default value
+ * is {@code true}.
+ *
+ * <p>If this extra is set to {@code true}, then when the provisioning flow returns back to the
+ * provisioning initiator, provisioning will not be complete. The provisioning initiator can
+ * use this opportunity to do its own preparatory steps prior to the launch of the admin app's
+ * {@link #ACTION_ADMIN_POLICY_COMPLIANCE} handler. It is the responsibility of the
+ * provisioning initiator to ensure that the provisioning flow is then resumed and completed.
+ *
+ * <p>If this extra is set to {@code false}, then when the provisioning flow returns back to
+ * the provisioning initiator, provisioning will be complete. Note that device owner
+ * provisioning is not currently supported for the this scenario.
+ *
+ * <p>This extra is only respected when provided alongside the {@link
+ * #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} intent action.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE =
+ "android.app.extra.PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE";
+
+ /**
* Activity action: Starts the administrator to show policy compliance for the provisioning.
* This action is used any time that the administrator has an opportunity to show policy
* compliance before the end of setup wizard. This could happen as part of the admin-integrated
@@ -2690,6 +2730,60 @@
/** @hide */
@TestApi
public static final int OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES = 22;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_CLEAR_APPLICATION_USER_DATA = 23;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_INSTALL_CA_CERT = 24;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_INSTALL_KEY_PAIR = 25;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_INSTALL_SYSTEM_UPDATE = 26;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_REMOVE_ACTIVE_ADMIN = 27;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_REMOVE_KEY_PAIR = 28;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_REQUEST_BUGREPORT = 29;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_ALWAYS_ON_VPN_PACKAGE = 30;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_CAMERA_DISABLED = 31;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY = 32;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_GLOBAL_PRIVATE_DNS = 33;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_LOGOUT_ENABLED = 34;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_MASTER_VOLUME_MUTED = 35;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_OVERRIDE_APNS_ENABLED = 36;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_PERMISSION_GRANT_STATE = 37;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_PERMISSION_POLICY = 38;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_RESTRICTIONS_PROVIDER = 39;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_UNINSTALL_CA_CERT = 40;
private static final String PREFIX_OPERATION = "OPERATION_";
@@ -2716,7 +2810,25 @@
OPERATION_SET_LOCK_TASK_PACKAGES,
OPERATION_SET_PACKAGES_SUSPENDED,
OPERATION_SET_TRUST_AGENT_CONFIGURATION,
- OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES
+ OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES,
+ OPERATION_CLEAR_APPLICATION_USER_DATA,
+ OPERATION_INSTALL_CA_CERT,
+ OPERATION_INSTALL_KEY_PAIR,
+ OPERATION_INSTALL_SYSTEM_UPDATE,
+ OPERATION_REMOVE_ACTIVE_ADMIN,
+ OPERATION_REMOVE_KEY_PAIR,
+ OPERATION_REQUEST_BUGREPORT,
+ OPERATION_SET_ALWAYS_ON_VPN_PACKAGE,
+ OPERATION_SET_CAMERA_DISABLED,
+ OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY,
+ OPERATION_SET_GLOBAL_PRIVATE_DNS,
+ OPERATION_SET_LOGOUT_ENABLED,
+ OPERATION_SET_MASTER_VOLUME_MUTED,
+ OPERATION_SET_OVERRIDE_APNS_ENABLED,
+ OPERATION_SET_PERMISSION_GRANT_STATE,
+ OPERATION_SET_PERMISSION_POLICY,
+ OPERATION_SET_RESTRICTIONS_PROVIDER,
+ OPERATION_UNINSTALL_CA_CERT
})
@Retention(RetentionPolicy.SOURCE)
public static @interface DevicePolicyOperation {
@@ -3025,7 +3137,9 @@
* Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the
* {@link DevicePolicyManager} instance returned by
* {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
- * profile. Apps targeting {@link android.os.Build.VERSION_CODES#S} and above will get a
+ * profile. Apps targeting {@link android.os.Build.VERSION_CODES#S} and above, with the
+ * exception of a profile owner on an organization-owned device (as can be identified by
+ * {@link #isOrganizationOwnedDeviceWithManagedProfile}), will get a
* {@code IllegalArgumentException} when calling this method on the parent
* {@link DevicePolicyManager} instance.
*
@@ -9821,7 +9935,7 @@
* Designates a specific service component as the provider for making permission requests of a
* local or remote administrator of the user.
* <p/>
- * Only a profile owner can designate the restrictions provider.
+ * Only a device owner or profile owner can designate the restrictions provider.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param provider The component name of the service that implements
@@ -12868,12 +12982,13 @@
* @throws SecurityException if the caller is not a profile owner or device owner.
*/
@NonNull public String getEnrollmentSpecificId() {
+ throwIfParentInstance("getEnrollmentSpecificId");
if (mService == null) {
return "";
}
try {
- return mService.getEnrollmentSpecificId();
+ return mService.getEnrollmentSpecificId(mContext.getPackageName());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -12890,6 +13005,7 @@
* enrolled into.
*/
public void setOrganizationId(@NonNull String enterpriseId) {
+ throwIfParentInstance("setOrganizationId");
setOrganizationIdForUser(mContext.getPackageName(), enterpriseId, myUserId());
}
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index ce2fd4f..a0d2977 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -231,7 +231,13 @@
* Returns the profile owner component for the given user, or {@code null} if there is not one.
*/
@Nullable
- public abstract ComponentName getProfileOwnerAsUser(int userHandle);
+ public abstract ComponentName getProfileOwnerAsUser(@UserIdInt int userId);
+
+ /**
+ * Returns the user id of the device owner, or {@link UserHandle#USER_NULL} if there is not one.
+ */
+ @UserIdInt
+ public abstract int getDeviceOwnerUserId();
/**
* Returns whether the given package is a device owner or a profile owner in the calling user.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index aaa5f7c..e855a1c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -491,6 +491,6 @@
void setNextOperationSafety(int operation, boolean safe);
- String getEnrollmentSpecificId();
+ String getEnrollmentSpecificId(String callerPackage);
void setOrganizationIdForUser(in String callerPackage, in String enterpriseId, int userId);
}
diff --git a/core/java/android/app/role/RoleControllerManager.java b/core/java/android/app/role/RoleControllerManager.java
index 8dde2c5..ba1f612 100644
--- a/core/java/android/app/role/RoleControllerManager.java
+++ b/core/java/android/app/role/RoleControllerManager.java
@@ -20,8 +20,6 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
-import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
@@ -48,8 +46,6 @@
*
* @hide
*/
-@SystemService(Context.ROLE_CONTROLLER_SERVICE)
-@TestApi
public class RoleControllerManager {
private static final String LOG_TAG = RoleControllerManager.class.getSimpleName();
@@ -199,32 +195,11 @@
}
/**
- * @see RoleControllerService#onIsApplicationQualifiedForRole(String, String)
- *
- * @deprecated Use {@link #isApplicationVisibleForRole(String, String, Executor, Consumer)}
- * instead.
- *
- * @hide
- */
- @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName,
- @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
- AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> {
- AndroidFuture<Bundle> future = new AndroidFuture<>();
- service.isApplicationQualifiedForRole(roleName, packageName,
- new RemoteCallback(future::complete));
- return future;
- });
- propagateCallback(operation, "isApplicationQualifiedForRole", executor, callback);
- }
-
- /**
* @see RoleControllerService#onIsApplicationVisibleForRole(String, String)
*
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- @TestApi
public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName,
@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> {
@@ -242,7 +217,6 @@
* @hide
*/
@RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
- @TestApi
public void isRoleVisible(@NonNull String roleName,
@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
AndroidFuture<Bundle> operation = mRemoteService.postAsync(service -> {
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index 8b2e07b..0fcf44d 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -174,6 +174,9 @@
@NonNull
private final Object mListenersLock = new Object();
+ @NonNull
+ private final RoleControllerManager mRoleControllerManager;
+
/**
* @hide
*/
@@ -181,6 +184,7 @@
mContext = context;
mService = IRoleManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
Context.ROLE_SERVICE));
+ mRoleControllerManager = new RoleControllerManager(context);
}
/**
@@ -676,6 +680,44 @@
}
}
+ /**
+ * Check whether a role should be visible to user.
+ *
+ * @param roleName name of the role to check for
+ * @param executor the executor to execute callback on
+ * @param callback the callback to receive whether the role should be visible to user
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+ @TestApi
+ public void isRoleVisible(@NonNull String roleName,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ mRoleControllerManager.isRoleVisible(roleName, executor, callback);
+ }
+
+ /**
+ * Check whether an application is visible for a role.
+ *
+ * While an application can be qualified for a role, it can still stay hidden from user (thus
+ * not visible). If an application is visible for a role, we may show things related to the role
+ * for it, e.g. showing an entry pointing to the role settings in its application info page.
+ *
+ * @param roleName the name of the role to check for
+ * @param packageName the package name of the application to check for
+ * @param executor the executor to execute callback on
+ * @param callback the callback to receive whether the application is visible for the role
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+ @TestApi
+ public void isApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ mRoleControllerManager.isApplicationVisibleForRole(roleName, packageName, executor,
+ callback);
+ }
+
private static class OnRoleHoldersChangedListenerDelegate
extends IOnRoleHoldersChangedListener.Stub {
diff --git a/core/java/android/app/search/OWNERS b/core/java/android/app/search/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/core/java/android/app/search/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/core/java/android/app/search/SearchAction.java b/core/java/android/app/search/SearchAction.java
index 158f9f3..a76154a 100644
--- a/core/java/android/app/search/SearchAction.java
+++ b/core/java/android/app/search/SearchAction.java
@@ -70,20 +70,20 @@
SearchAction(Parcel in) {
mId = in.readString();
- mIcon = Icon.CREATOR.createFromParcel(in);
mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ mIcon = in.readTypedObject(Icon.CREATOR);
mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- mPendingIntent = PendingIntent.CREATOR.createFromParcel(in);
- mIntent = Intent.CREATOR.createFromParcel(in);
+ mPendingIntent = in.readTypedObject(PendingIntent.CREATOR);
+ mIntent = in.readTypedObject(Intent.CREATOR);
mUserHandle = in.readTypedObject(UserHandle.CREATOR);
- mExtras = in.readBundle();
+ mExtras = in.readTypedObject(Bundle.CREATOR);
}
private SearchAction(
@NonNull String id,
- @Nullable Icon icon,
@NonNull CharSequence title,
+ @Nullable Icon icon,
@Nullable CharSequence subtitle,
@Nullable CharSequence contentDescription,
@Nullable PendingIntent pendingIntent,
@@ -91,8 +91,8 @@
@Nullable UserHandle userHandle,
@Nullable Bundle extras) {
mId = Objects.requireNonNull(id);
- mIcon = icon;
mTitle = Objects.requireNonNull(title);
+ mIcon = icon;
mSubtitle = subtitle;
mContentDescription = contentDescription;
mPendingIntent = pendingIntent;
@@ -192,14 +192,14 @@
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeString(mId);
- out.writeTypedObject(mIcon, flags);
TextUtils.writeToParcel(mTitle, out, flags);
+ out.writeTypedObject(mIcon, flags);
TextUtils.writeToParcel(mSubtitle, out, flags);
TextUtils.writeToParcel(mContentDescription, out, flags);
out.writeTypedObject(mPendingIntent, flags);
out.writeTypedObject(mIntent, flags);
out.writeTypedObject(mUserHandle, flags);
- out.writeBundle(mExtras);
+ out.writeTypedObject(mExtras, flags);
}
@Override
@@ -235,13 +235,13 @@
@NonNull
private String mId;
- @Nullable
- private Icon mIcon;
-
@NonNull
private CharSequence mTitle;
@Nullable
+ private Icon mIcon;
+
+ @Nullable
private CharSequence mSubtitle;
@Nullable
@@ -337,7 +337,7 @@
*/
@NonNull
public SearchAction build() {
- return new SearchAction(mId, mIcon, mTitle, mSubtitle, mContentDescription,
+ return new SearchAction(mId, mTitle, mIcon, mSubtitle, mContentDescription,
mPendingIntent, mIntent, mUserHandle, mExtras);
}
}
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index ee718b35..b216e91 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -55,12 +55,6 @@
String SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED = "is_geo_detection_supported";
/**
- * A shell command that prints the current user's "location enabled" setting.
- * @hide
- */
- String SHELL_COMMAND_IS_LOCATION_ENABLED = "is_location_enabled";
-
- /**
* A shell command that prints the current user's "location-based time zone detection enabled"
* setting.
* @hide
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index c0cb323..15daf1c 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -118,7 +118,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
public static final String ACTION_ACTIVE_DEVICE_CHANGED =
"android.bluetooth.a2dp.profile.action.ACTIVE_DEVICE_CHANGED";
@@ -409,7 +409,7 @@
* @hide
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
try {
@@ -433,7 +433,7 @@
* is active
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
@Nullable
@RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothDevice getActiveDevice() {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 406fe8d..7eda50e 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1174,7 +1174,7 @@
* @return true to indicate adapter shutdown has begun, or false on immediate error
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
public boolean disable(boolean persist) {
try {
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 4161096..d6b38fd 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -113,7 +113,7 @@
* @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
public static final String ACTION_ACTIVE_DEVICE_CHANGED =
"android.bluetooth.headset.profile.action.ACTIVE_DEVICE_CHANGED";
@@ -1172,7 +1172,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) {
Log.d(TAG, "setActiveDevice: " + device);
@@ -1198,7 +1198,7 @@
* is active.
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
@Nullable
@RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothDevice getActiveDevice() {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 5ccceca..eb70ae1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4833,16 +4833,6 @@
public static final String ROLE_SERVICE = "role";
/**
- * Official published name of the (internal) role controller service.
- *
- * @see #getSystemService(String)
- * @see android.app.role.RoleControllerService
- *
- * @hide
- */
- public static final String ROLE_CONTROLLER_SERVICE = "role_controller";
-
- /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.hardware.camera2.CameraManager} for interacting with
* camera devices.
@@ -5096,9 +5086,7 @@
* Service to capture a bugreport.
* @see #getSystemService(String)
* @see android.os.BugreportManager
- * @hide
*/
- @SystemApi
public static final String BUGREPORT_SERVICE = "bugreport";
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a03bdf2..13a1381 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2393,8 +2393,19 @@
* Broadcast Action: This is broadcast when a user action should request a
* temporary system dialog to dismiss. Some examples of temporary system
* dialogs are the notification window-shade and the recent tasks dialog.
+ *
+ * @deprecated This intent is deprecated for third-party applications starting from Android
+ * {@link Build.VERSION_CODES#S} for security reasons. Unauthorized usage by applications
+ * will result in the broadcast intent being dropped for apps targeting API level less than
+ * {@link Build.VERSION_CODES#S} and in a {@link SecurityException} for apps targeting SDK
+ * level {@link Build.VERSION_CODES#S} or higher. Instrumentation initiated from the shell
+ * (eg. tests) is still able to use the intent. The platform will automatically collapse
+ * the proper system dialogs in the proper use-cases. For all others, the user is the one in
+ * control of closing dialogs.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @RequiresPermission(android.Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS)
+ @Deprecated
public static final String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
/**
* Broadcast Action: Trigger the download and eventual installation
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index f063359..c5badb9 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -150,6 +150,7 @@
private static final String AGLOB_STR = "aglob";
private static final String SGLOB_STR = "sglob";
private static final String PREFIX_STR = "prefix";
+ private static final String SUFFIX_STR = "suffix";
private static final String LITERAL_STR = "literal";
private static final String PATH_STR = "path";
private static final String PORT_STR = "port";
@@ -1226,7 +1227,8 @@
* path, or a simple pattern, depending on <var>type</var>.
* @param type Determines how <var>ssp</var> will be compared to
* determine a match: either {@link PatternMatcher#PATTERN_LITERAL},
- * {@link PatternMatcher#PATTERN_PREFIX}, or
+ * {@link PatternMatcher#PATTERN_PREFIX},
+ * {@link PatternMatcher#PATTERN_SUFFIX}, or
* {@link PatternMatcher#PATTERN_SIMPLE_GLOB}.
*
* @see #matchData
@@ -1419,7 +1421,8 @@
* path, or a simple pattern, depending on <var>type</var>.
* @param type Determines how <var>path</var> will be compared to
* determine a match: either {@link PatternMatcher#PATTERN_LITERAL},
- * {@link PatternMatcher#PATTERN_PREFIX}, or
+ * {@link PatternMatcher#PATTERN_PREFIX},
+ * {@link PatternMatcher#PATTERN_SUFFIX}, or
* {@link PatternMatcher#PATTERN_SIMPLE_GLOB}.
*
* @see #matchData
@@ -1920,6 +1923,9 @@
case PatternMatcher.PATTERN_ADVANCED_GLOB:
serializer.attribute(null, AGLOB_STR, pe.getPath());
break;
+ case PatternMatcher.PATTERN_SUFFIX:
+ serializer.attribute(null, SUFFIX_STR, pe.getPath());
+ break;
}
serializer.endTag(null, SSP_STR);
}
@@ -1950,6 +1956,9 @@
case PatternMatcher.PATTERN_ADVANCED_GLOB:
serializer.attribute(null, AGLOB_STR, pe.getPath());
break;
+ case PatternMatcher.PATTERN_SUFFIX:
+ serializer.attribute(null, SUFFIX_STR, pe.getPath());
+ break;
}
serializer.endTag(null, PATH_STR);
}
@@ -2057,6 +2066,8 @@
addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_SIMPLE_GLOB);
} else if ((ssp=parser.getAttributeValue(null, AGLOB_STR)) != null) {
addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_ADVANCED_GLOB);
+ } else if ((ssp=parser.getAttributeValue(null, SUFFIX_STR)) != null) {
+ addDataSchemeSpecificPart(ssp, PatternMatcher.PATTERN_SUFFIX);
}
} else if (tagName.equals(AUTH_STR)) {
String host = parser.getAttributeValue(null, HOST_STR);
@@ -2074,6 +2085,8 @@
addDataPath(path, PatternMatcher.PATTERN_SIMPLE_GLOB);
} else if ((path=parser.getAttributeValue(null, AGLOB_STR)) != null) {
addDataPath(path, PatternMatcher.PATTERN_ADVANCED_GLOB);
+ } else if ((path=parser.getAttributeValue(null, SUFFIX_STR)) != null) {
+ addDataPath(path, PatternMatcher.PATTERN_SUFFIX);
}
} else {
Log.w("IntentFilter", "Unknown tag parsing IntentFilter: " + tagName);
diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS
index c1e7e41..144856b 100644
--- a/core/java/android/content/OWNERS
+++ b/core/java/android/content/OWNERS
@@ -1,3 +1,7 @@
# Remain no owner because multiple modules may touch this file.
per-file Context.java = *
per-file ContextWrapper.java = *
+per-file IntentFilter.java = toddke@google.com
+per-file IntentFilter.java = patb@google.com
+per-file Intent.java = toddke@google.com
+per-file Intent.java = patb@google.com
\ No newline at end of file
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index f634b8a..7c0b821 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -65,7 +65,7 @@
*/
interface IPackageManager {
void checkPackageStartable(String packageName, int userId);
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
boolean isPackageAvailable(String packageName, int userId);
@UnsupportedAppUsage
PackageInfo getPackageInfo(String packageName, int flags, int userId);
diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS
index fd32efc..f0def805 100644
--- a/core/java/android/content/pm/OWNERS
+++ b/core/java/android/content/pm/OWNERS
@@ -6,5 +6,6 @@
per-file PackageParser.java = chiuwinson@google.com
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+per-file AppSearchPerson.java = file:/core/java/android/content/pm/SHORTCUT_OWNERS
per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS
per-file UserInfo* = file:/MULTIUSER_OWNERS
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 17c4d25..03d4d5e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3513,6 +3513,17 @@
public static final String FEATURE_TUNER = "android.hardware.tv.tuner";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device supports a enabling/disabling sensor privacy for
+ * camera. When sensory privacy for the camera is enabled no camera data is send to clients,
+ * e.g. the view finder in a camera app would appear blank.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
+
+ /**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
* the necessary changes to support app enumeration.
*
diff --git a/core/java/android/content/pm/parsing/ApkLite.java b/core/java/android/content/pm/parsing/ApkLite.java
new file mode 100644
index 0000000..d8ec512
--- /dev/null
+++ b/core/java/android/content/pm/parsing/ApkLite.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.content.pm.parsing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageParser.SigningDetails;
+import android.content.pm.VerifierInfo;
+
+import com.android.internal.util.DataClass;
+
+import java.util.List;
+
+/**
+ * Lightweight parsed details about a single APK file.
+ *
+ * @hide
+ */
+@DataClass(genConstructor = false, genConstDefs = false)
+public class ApkLite {
+ /** Name of the package as used to identify it in the system */
+ private final @NonNull String mPackageName;
+ /** Path where this APK file was found on disk */
+ private final @NonNull String mPath;
+ /** Split name of this APK */
+ private final @Nullable String mSplitName;
+ /** Dependencies of the split APK */
+ /** Name of the split APK that this APK depends on */
+ private final @Nullable String mUsesSplitName;
+ /** Name of the split APK that this APK is a configuration for */
+ private final @Nullable String mConfigForSplit;
+
+ /** Major version number of this package */
+ private final int mVersionCodeMajor;
+ /** Minor version number of this package */
+ private final int mVersionCode;
+ /** Revision code of this APK */
+ private final int mRevisionCode;
+ /**
+ * Indicate the install location of this package
+ *
+ * @see {@link PackageInfo#INSTALL_LOCATION_AUTO}
+ * @see {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}
+ * @see {@link PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL}
+ */
+ private final int mInstallLocation;
+ /** Indicate the minimum SDK version number that the app requires */
+ private final int mMinSdkVersion;
+ /** Indicate the SDK version number that the application is targeting */
+ private final int mTargetSdkVersion;
+ /** Information about a package verifiers as used during package verification */
+ private final @NonNull VerifierInfo[] mVerifiers;
+ /** Signing-related data of an application package */
+ private final @NonNull SigningDetails mSigningDetails;
+
+ /** Indicate whether this APK is a 'feature' split */
+ private final boolean mFeatureSplit;
+ /** Indicate whether each split should be load into their own Context objects */
+ private final boolean mIsolatedSplits;
+ /**
+ * Indicate whether this package requires at least one split (either feature or resource)
+ * to be present in order to function
+ */
+ private final boolean mSplitRequired;
+ /** Indicate whether this app is coreApp */
+ private final boolean mCoreApp;
+ /** Indicate whether this app can be debugged */
+ private final boolean mDebuggable;
+ /** Indicate whether this app is profileable by Shell */
+ private final boolean mProfileableByShell;
+ /** Indicate whether this app needs to be loaded into other applications' processes */
+ private final boolean mMultiArch;
+ /** Indicate whether the 32 bit version of the ABI should be used */
+ private final boolean mUse32bitAbi;
+ /** Indicate whether installer extracts native libraries */
+ private final boolean mExtractNativeLibs;
+ /**
+ * Indicate whether this package wants to run the dex within its APK but not extracted
+ * or locally compiled variants.
+ */
+ private final boolean mUseEmbeddedDex;
+
+ /** Name of the overlay-able set of elements package */
+ private final @Nullable String mTargetPackageName;
+ /** Indicate whether the overlay is static */
+ private final boolean mOverlayIsStatic;
+ /** Indicate the priority of this overlay package */
+ private final int mOverlayPriority;
+
+ /**
+ * Indicate the policy to deal with user data when rollback is committed
+ *
+ * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#RESTORE}
+ * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#WIPE}
+ * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#RETAIN}
+ */
+ private final int mRollbackDataPolicy;
+
+ public ApkLite(String path, String packageName, String splitName, boolean isFeatureSplit,
+ String configForSplit, String usesSplitName, boolean isSplitRequired, int versionCode,
+ int versionCodeMajor, int revisionCode, int installLocation,
+ List<VerifierInfo> verifiers, SigningDetails signingDetails, boolean coreApp,
+ boolean debuggable, boolean profileableByShell, boolean multiArch, boolean use32bitAbi,
+ boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits,
+ String targetPackageName, boolean overlayIsStatic, int overlayPriority,
+ int minSdkVersion, int targetSdkVersion, int rollbackDataPolicy) {
+ mPath = path;
+ mPackageName = packageName;
+ mSplitName = splitName;
+ mFeatureSplit = isFeatureSplit;
+ mConfigForSplit = configForSplit;
+ mUsesSplitName = usesSplitName;
+ mSplitRequired = isSplitRequired;
+ mVersionCode = versionCode;
+ mVersionCodeMajor = versionCodeMajor;
+ mRevisionCode = revisionCode;
+ mInstallLocation = installLocation;
+ mVerifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
+ mSigningDetails = signingDetails;
+ mCoreApp = coreApp;
+ mDebuggable = debuggable;
+ mProfileableByShell = profileableByShell;
+ mMultiArch = multiArch;
+ mUse32bitAbi = use32bitAbi;
+ mUseEmbeddedDex = useEmbeddedDex;
+ mExtractNativeLibs = extractNativeLibs;
+ mIsolatedSplits = isolatedSplits;
+ mTargetPackageName = targetPackageName;
+ mOverlayIsStatic = overlayIsStatic;
+ mOverlayPriority = overlayPriority;
+ mMinSdkVersion = minSdkVersion;
+ mTargetSdkVersion = targetSdkVersion;
+ mRollbackDataPolicy = rollbackDataPolicy;
+ }
+
+ /**
+ * Return {@link #mVersionCode} and {@link #mVersionCodeMajor} combined together as a
+ * single long value. The {@link #mVersionCodeMajor} is placed in the upper 32 bits.
+ */
+ public long getLongVersionCode() {
+ return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
+ }
+
+
+
+ // Code below generated by codegen v1.0.22.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/ApkLite.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Name of the package as used to identify it in the system
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Path where this APK file was found on disk
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getPath() {
+ return mPath;
+ }
+
+ /**
+ * Split name of this APK
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getSplitName() {
+ return mSplitName;
+ }
+
+ /**
+ * Name of the split APK that this APK depends on
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getUsesSplitName() {
+ return mUsesSplitName;
+ }
+
+ /**
+ * Name of the split APK that this APK is a configuration for
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getConfigForSplit() {
+ return mConfigForSplit;
+ }
+
+ /**
+ * Major version number of this package
+ */
+ @DataClass.Generated.Member
+ public int getVersionCodeMajor() {
+ return mVersionCodeMajor;
+ }
+
+ /**
+ * Minor version number of this package
+ */
+ @DataClass.Generated.Member
+ public int getVersionCode() {
+ return mVersionCode;
+ }
+
+ /**
+ * Revision code of this APK
+ */
+ @DataClass.Generated.Member
+ public int getRevisionCode() {
+ return mRevisionCode;
+ }
+
+ /**
+ * Indicate the install location of this package
+ *
+ * @see {@link PackageInfo#INSTALL_LOCATION_AUTO}
+ * @see {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}
+ * @see {@link PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL}
+ */
+ @DataClass.Generated.Member
+ public int getInstallLocation() {
+ return mInstallLocation;
+ }
+
+ /**
+ * Indicate the minimum SDK version number that the app requires
+ */
+ @DataClass.Generated.Member
+ public int getMinSdkVersion() {
+ return mMinSdkVersion;
+ }
+
+ /**
+ * Indicate the SDK version number that the application is targeting
+ */
+ @DataClass.Generated.Member
+ public int getTargetSdkVersion() {
+ return mTargetSdkVersion;
+ }
+
+ /**
+ * Information about a package verifiers as used during package verification
+ */
+ @DataClass.Generated.Member
+ public @NonNull VerifierInfo[] getVerifiers() {
+ return mVerifiers;
+ }
+
+ /**
+ * Signing-related data of an application package
+ */
+ @DataClass.Generated.Member
+ public @NonNull SigningDetails getSigningDetails() {
+ return mSigningDetails;
+ }
+
+ /**
+ * Indicate whether this APK is a 'feature' split
+ */
+ @DataClass.Generated.Member
+ public boolean isFeatureSplit() {
+ return mFeatureSplit;
+ }
+
+ /**
+ * Indicate whether each split should be load into their own Context objects
+ */
+ @DataClass.Generated.Member
+ public boolean isIsolatedSplits() {
+ return mIsolatedSplits;
+ }
+
+ /**
+ * Indicate whether this package requires at least one split (either feature or resource)
+ * to be present in order to function
+ */
+ @DataClass.Generated.Member
+ public boolean isSplitRequired() {
+ return mSplitRequired;
+ }
+
+ /**
+ * Indicate whether this app is coreApp
+ */
+ @DataClass.Generated.Member
+ public boolean isCoreApp() {
+ return mCoreApp;
+ }
+
+ /**
+ * Indicate whether this app can be debugged
+ */
+ @DataClass.Generated.Member
+ public boolean isDebuggable() {
+ return mDebuggable;
+ }
+
+ /**
+ * Indicate whether this app is profileable by Shell
+ */
+ @DataClass.Generated.Member
+ public boolean isProfileableByShell() {
+ return mProfileableByShell;
+ }
+
+ /**
+ * Indicate whether this app needs to be loaded into other applications' processes
+ */
+ @DataClass.Generated.Member
+ public boolean isMultiArch() {
+ return mMultiArch;
+ }
+
+ /**
+ * Indicate whether the 32 bit version of the ABI should be used
+ */
+ @DataClass.Generated.Member
+ public boolean isUse32bitAbi() {
+ return mUse32bitAbi;
+ }
+
+ /**
+ * Indicate whether installer extracts native libraries
+ */
+ @DataClass.Generated.Member
+ public boolean isExtractNativeLibs() {
+ return mExtractNativeLibs;
+ }
+
+ /**
+ * Indicate whether this package wants to run the dex within its APK but not extracted
+ * or locally compiled variants.
+ */
+ @DataClass.Generated.Member
+ public boolean isUseEmbeddedDex() {
+ return mUseEmbeddedDex;
+ }
+
+ /**
+ * Name of the overlay-able set of elements package
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getTargetPackageName() {
+ return mTargetPackageName;
+ }
+
+ /**
+ * Indicate whether the overlay is static
+ */
+ @DataClass.Generated.Member
+ public boolean isOverlayIsStatic() {
+ return mOverlayIsStatic;
+ }
+
+ /**
+ * Indicate the priority of this overlay package
+ */
+ @DataClass.Generated.Member
+ public int getOverlayPriority() {
+ return mOverlayPriority;
+ }
+
+ /**
+ * Indicate the policy to deal with user data when rollback is committed
+ *
+ * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#RESTORE}
+ * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#WIPE}
+ * @see {@link android.content.pm.PackageManager.RollbackDataPolicy#RETAIN}
+ */
+ @DataClass.Generated.Member
+ public int getRollbackDataPolicy() {
+ return mRollbackDataPolicy;
+ }
+
+ @DataClass.Generated(
+ time = 1610596637723L,
+ codegenVersion = "1.0.22",
+ sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ApkLite.java",
+ inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.Nullable java.lang.String mUsesSplitName\nprivate final @android.annotation.Nullable java.lang.String mConfigForSplit\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mRevisionCode\nprivate final int mInstallLocation\nprivate final int mMinSdkVersion\nprivate final int mTargetSdkVersion\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.NonNull android.content.pm.PackageParser.SigningDetails mSigningDetails\nprivate final boolean mFeatureSplit\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mProfileableByShell\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mUseEmbeddedDex\nprivate final @android.annotation.Nullable java.lang.String mTargetPackageName\nprivate final boolean mOverlayIsStatic\nprivate final int mOverlayPriority\nprivate final int mRollbackDataPolicy\npublic long getLongVersionCode()\nclass ApkLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index f583e25..51b81b6 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -18,7 +18,6 @@
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
import static android.content.pm.parsing.ParsingPackageUtils.validateName;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
@@ -51,6 +50,7 @@
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
import java.util.Objects;
@@ -66,6 +66,8 @@
private static final int PARSE_DEFAULT_INSTALL_LOCATION =
PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ public static final String APK_FILE_EXTENSION = ".apk";
+
/**
* Parse only lightweight details about the package at the given location.
* Automatically detects if the package is a monolithic style (single APK
@@ -606,4 +608,21 @@
return new VerifierInfo(packageName, publicKey);
}
+
+ /**
+ * Used to sort a set of APKs based on their split names, always placing the
+ * base APK (with {@code null} split name) first.
+ */
+ private static class SplitNameComparator implements Comparator<String> {
+ @Override
+ public int compare(String lhs, String rhs) {
+ if (lhs == null) {
+ return -1;
+ } else if (rhs == null) {
+ return 1;
+ } else {
+ return lhs.compareTo(rhs);
+ }
+ }
+ }
}
diff --git a/core/java/android/content/pm/parsing/PackageLite.java b/core/java/android/content/pm/parsing/PackageLite.java
new file mode 100644
index 0000000..803d643
--- /dev/null
+++ b/core/java/android/content/pm/parsing/PackageLite.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.content.pm.parsing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageInfo;
+import android.content.pm.VerifierInfo;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lightweight parsed details about a single package.
+ *
+ * @hide
+ */
+@DataClass(genConstructor = false, genConstDefs = false)
+public class PackageLite {
+ /** Name of the package as used to identify it in the system */
+ private final @NonNull String mPackageName;
+ /**
+ * Path where this package was found on disk. For monolithic packages
+ * this is path to single base APK file; for cluster packages this is
+ * path to the cluster directory.
+ */
+ private final @NonNull String mPath;
+ /** Path of base APK */
+ private final @NonNull String mBaseApkPath;
+ /** Paths of any split APKs, ordered by parsed splitName */
+ private final @Nullable String[] mSplitApkPaths;
+ /** Names of any split APKs, ordered by parsed splitName */
+ private final @Nullable String[] mSplitNames;
+ /** Dependencies of any split APKs, ordered by parsed splitName */
+ private final @Nullable String[] mUsesSplitNames;
+ private final @Nullable String[] mConfigForSplit;
+ /** Major and minor version number of this package */
+ private final int mVersionCodeMajor;
+ private final int mVersionCode;
+ /** Revision code of base APK */
+ private final int mBaseRevisionCode;
+ /** Revision codes of any split APKs, ordered by parsed splitName */
+ private final @Nullable int[] mSplitRevisionCodes;
+ /**
+ * Indicate the install location of this package
+ *
+ * @see {@link PackageInfo#INSTALL_LOCATION_AUTO}
+ * @see {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}
+ * @see {@link PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL}
+ */
+ private final int mInstallLocation;
+ /** Information about a package verifiers as used during package verification */
+ private final @NonNull VerifierInfo[] mVerifiers;
+
+ /** Indicate whether any split APKs that are features. Ordered by splitName */
+ private final @Nullable boolean[] mIsFeatureSplits;
+ /** Indicate whether each split should be load into their own Context objects */
+ private final boolean mIsolatedSplits;
+ /**
+ * Indicate whether this package requires at least one split (either feature or resource)
+ * to be present in order to function
+ */
+ private final boolean mSplitRequired;
+ /** Indicate whether this app is coreApp */
+ private final boolean mCoreApp;
+ /** Indicate whether this app can be debugged */
+ private final boolean mDebuggable;
+ /** Indicate whether this app needs to be loaded into other applications' processes */
+ private final boolean mMultiArch;
+ /** Indicate whether the 32 bit version of the ABI should be used */
+ private final boolean mUse32bitAbi;
+ /** Indicate whether installer extracts native libraries */
+ private final boolean mExtractNativeLibs;
+ /** Indicate whether this app is profileable by Shell */
+ private final boolean mProfileableByShell;
+ /**
+ * Indicate whether this package wants to run the dex within its APK but not extracted
+ * or locally compiled variants.
+ */
+ private final boolean mUseEmbeddedDex;
+
+ public PackageLite(String path, String baseApkPath, ApkLite baseApk,
+ String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames,
+ String[] configForSplit, String[] splitApkPaths, int[] splitRevisionCodes) {
+ // The following paths may be different from the path in ApkLite because we
+ // move or rename the APK files. Use parameters to indicate the correct paths.
+ mPath = path;
+ mBaseApkPath = baseApkPath;
+ mPackageName = baseApk.getPackageName();
+ mVersionCode = baseApk.getVersionCode();
+ mVersionCodeMajor = baseApk.getVersionCodeMajor();
+ mInstallLocation = baseApk.getInstallLocation();
+ mVerifiers = baseApk.getVerifiers();
+ mBaseRevisionCode = baseApk.getRevisionCode();
+ mCoreApp = baseApk.isCoreApp();
+ mDebuggable = baseApk.isDebuggable();
+ mMultiArch = baseApk.isMultiArch();
+ mUse32bitAbi = baseApk.isUse32bitAbi();
+ mExtractNativeLibs = baseApk.isExtractNativeLibs();
+ mIsolatedSplits = baseApk.isIsolatedSplits();
+ mUseEmbeddedDex = baseApk.isUseEmbeddedDex();
+ mSplitRequired = baseApk.isSplitRequired();
+ mProfileableByShell = baseApk.isProfileableByShell();
+ mSplitNames = splitNames;
+ mIsFeatureSplits = isFeatureSplits;
+ mUsesSplitNames = usesSplitNames;
+ mConfigForSplit = configForSplit;
+ mSplitApkPaths = splitApkPaths;
+ mSplitRevisionCodes = splitRevisionCodes;
+ }
+
+ /**
+ * Return code path to the base APK file, and split APK files if any.
+ */
+ public List<String> getAllApkPaths() {
+ final ArrayList<String> paths = new ArrayList<>();
+ paths.add(mBaseApkPath);
+ if (!ArrayUtils.isEmpty(mSplitApkPaths)) {
+ Collections.addAll(paths, mSplitApkPaths);
+ }
+ return paths;
+ }
+
+ /**
+ * Return {@link #mVersionCode} and {@link #mVersionCodeMajor} combined together as a
+ * single long value. The {@link #mVersionCodeMajor} is placed in the upper 32 bits.
+ */
+ public long getLongVersionCode() {
+ return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
+ }
+
+
+
+ // Code below generated by codegen v1.0.22.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/PackageLite.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Name of the package as used to identify it in the system
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Path where this package was found on disk. For monolithic packages
+ * this is path to single base APK file; for cluster packages this is
+ * path to the cluster directory.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getPath() {
+ return mPath;
+ }
+
+ /**
+ * Path of base APK
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getBaseApkPath() {
+ return mBaseApkPath;
+ }
+
+ /**
+ * Paths of any split APKs, ordered by parsed splitName
+ */
+ @DataClass.Generated.Member
+ public @Nullable String[] getSplitApkPaths() {
+ return mSplitApkPaths;
+ }
+
+ /**
+ * Names of any split APKs, ordered by parsed splitName
+ */
+ @DataClass.Generated.Member
+ public @Nullable String[] getSplitNames() {
+ return mSplitNames;
+ }
+
+ /**
+ * Dependencies of any split APKs, ordered by parsed splitName
+ */
+ @DataClass.Generated.Member
+ public @Nullable String[] getUsesSplitNames() {
+ return mUsesSplitNames;
+ }
+
+ @DataClass.Generated.Member
+ public @Nullable String[] getConfigForSplit() {
+ return mConfigForSplit;
+ }
+
+ /**
+ * Major and minor version number of this package
+ */
+ @DataClass.Generated.Member
+ public int getVersionCodeMajor() {
+ return mVersionCodeMajor;
+ }
+
+ @DataClass.Generated.Member
+ public int getVersionCode() {
+ return mVersionCode;
+ }
+
+ /**
+ * Revision code of base APK
+ */
+ @DataClass.Generated.Member
+ public int getBaseRevisionCode() {
+ return mBaseRevisionCode;
+ }
+
+ /**
+ * Revision codes of any split APKs, ordered by parsed splitName
+ */
+ @DataClass.Generated.Member
+ public @Nullable int[] getSplitRevisionCodes() {
+ return mSplitRevisionCodes;
+ }
+
+ /**
+ * Indicate the install location of this package
+ *
+ * @see {@link PackageInfo#INSTALL_LOCATION_AUTO}
+ * @see {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}
+ * @see {@link PackageInfo#INSTALL_LOCATION_PREFER_EXTERNAL}
+ */
+ @DataClass.Generated.Member
+ public int getInstallLocation() {
+ return mInstallLocation;
+ }
+
+ /**
+ * Information about a package verifiers as used during package verification
+ */
+ @DataClass.Generated.Member
+ public @NonNull VerifierInfo[] getVerifiers() {
+ return mVerifiers;
+ }
+
+ /**
+ * Indicate whether any split APKs that are features. Ordered by splitName
+ */
+ @DataClass.Generated.Member
+ public @Nullable boolean[] getIsFeatureSplits() {
+ return mIsFeatureSplits;
+ }
+
+ /**
+ * Indicate whether each split should be load into their own Context objects
+ */
+ @DataClass.Generated.Member
+ public boolean isIsolatedSplits() {
+ return mIsolatedSplits;
+ }
+
+ /**
+ * Indicate whether this package requires at least one split (either feature or resource)
+ * to be present in order to function
+ */
+ @DataClass.Generated.Member
+ public boolean isSplitRequired() {
+ return mSplitRequired;
+ }
+
+ /**
+ * Indicate whether this app is coreApp
+ */
+ @DataClass.Generated.Member
+ public boolean isCoreApp() {
+ return mCoreApp;
+ }
+
+ /**
+ * Indicate whether this app can be debugged
+ */
+ @DataClass.Generated.Member
+ public boolean isDebuggable() {
+ return mDebuggable;
+ }
+
+ /**
+ * Indicate whether this app needs to be loaded into other applications' processes
+ */
+ @DataClass.Generated.Member
+ public boolean isMultiArch() {
+ return mMultiArch;
+ }
+
+ /**
+ * Indicate whether the 32 bit version of the ABI should be used
+ */
+ @DataClass.Generated.Member
+ public boolean isUse32bitAbi() {
+ return mUse32bitAbi;
+ }
+
+ /**
+ * Indicate whether installer extracts native libraries
+ */
+ @DataClass.Generated.Member
+ public boolean isExtractNativeLibs() {
+ return mExtractNativeLibs;
+ }
+
+ /**
+ * Indicate whether this app is profileable by Shell
+ */
+ @DataClass.Generated.Member
+ public boolean isProfileableByShell() {
+ return mProfileableByShell;
+ }
+
+ /**
+ * Indicate whether this package wants to run the dex within its APK but not extracted
+ * or locally compiled variants.
+ */
+ @DataClass.Generated.Member
+ public boolean isUseEmbeddedDex() {
+ return mUseEmbeddedDex;
+ }
+
+ @DataClass.Generated(
+ time = 1610596639255L,
+ codegenVersion = "1.0.22",
+ sourceFile = "frameworks/base/core/java/android/content/pm/parsing/PackageLite.java",
+ inputSignatures = "private final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.NonNull java.lang.String mPath\nprivate final @android.annotation.NonNull java.lang.String mBaseApkPath\nprivate final @android.annotation.Nullable java.lang.String[] mSplitApkPaths\nprivate final @android.annotation.Nullable java.lang.String[] mSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mUsesSplitNames\nprivate final @android.annotation.Nullable java.lang.String[] mConfigForSplit\nprivate final int mVersionCodeMajor\nprivate final int mVersionCode\nprivate final int mBaseRevisionCode\nprivate final @android.annotation.Nullable int[] mSplitRevisionCodes\nprivate final int mInstallLocation\nprivate final @android.annotation.NonNull android.content.pm.VerifierInfo[] mVerifiers\nprivate final @android.annotation.Nullable boolean[] mIsFeatureSplits\nprivate final boolean mIsolatedSplits\nprivate final boolean mSplitRequired\nprivate final boolean mCoreApp\nprivate final boolean mDebuggable\nprivate final boolean mMultiArch\nprivate final boolean mUse32bitAbi\nprivate final boolean mExtractNativeLibs\nprivate final boolean mProfileableByShell\nprivate final boolean mUseEmbeddedDex\npublic java.util.List<java.lang.String> getAllApkPaths()\npublic long getLongVersionCode()\nclass PackageLite extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genConstDefs=false)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index 561a9e3..494b3cc 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -29,6 +29,7 @@
import android.annotation.AnyRes;
import android.annotation.CheckResult;
+import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -112,6 +113,8 @@
import java.io.File;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
@@ -130,6 +133,82 @@
private static final String TAG = ParsingUtils.TAG;
+ public static final boolean DEBUG_JAR = false;
+ public static final boolean DEBUG_BACKUP = false;
+ public static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f;
+
+ /** File name in an APK for the Android manifest. */
+ public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
+
+ /** Path prefix for apps on expanded storage */
+ public static final String MNT_EXPAND = "/mnt/expand/";
+
+ public static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions";
+ public static final String TAG_APPLICATION = "application";
+ public static final String TAG_COMPATIBLE_SCREENS = "compatible-screens";
+ public static final String TAG_EAT_COMMENT = "eat-comment";
+ public static final String TAG_FEATURE_GROUP = "feature-group";
+ public static final String TAG_INSTRUMENTATION = "instrumentation";
+ public static final String TAG_KEY_SETS = "key-sets";
+ public static final String TAG_MANIFEST = "manifest";
+ public static final String TAG_ORIGINAL_PACKAGE = "original-package";
+ public static final String TAG_OVERLAY = "overlay";
+ public static final String TAG_PACKAGE = "package";
+ public static final String TAG_PACKAGE_VERIFIER = "package-verifier";
+ public static final String TAG_ATTRIBUTION = "attribution";
+ public static final String TAG_PERMISSION = "permission";
+ public static final String TAG_PERMISSION_GROUP = "permission-group";
+ public static final String TAG_PERMISSION_TREE = "permission-tree";
+ public static final String TAG_PROTECTED_BROADCAST = "protected-broadcast";
+ public static final String TAG_QUERIES = "queries";
+ public static final String TAG_RESTRICT_UPDATE = "restrict-update";
+ public static final String TAG_SUPPORT_SCREENS = "supports-screens";
+ public static final String TAG_SUPPORTS_INPUT = "supports-input";
+ public static final String TAG_USES_CONFIGURATION = "uses-configuration";
+ public static final String TAG_USES_FEATURE = "uses-feature";
+ public static final String TAG_USES_GL_TEXTURE = "uses-gl-texture";
+ public static final String TAG_USES_PERMISSION = "uses-permission";
+ public static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23";
+ public static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m";
+ public static final String TAG_USES_SDK = "uses-sdk";
+ public static final String TAG_USES_SPLIT = "uses-split";
+ public static final String TAG_PROFILEABLE = "profileable";
+
+ public static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
+ public static final String METADATA_SUPPORTS_SIZE_CHANGES = "android.supports_size_changes";
+ public static final String METADATA_ACTIVITY_WINDOW_LAYOUT_AFFINITY =
+ "android.activity_window_layout_affinity";
+
+ public static final int SDK_VERSION = Build.VERSION.SDK_INT;
+ public static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
+
+ public static boolean sCompatibilityModeEnabled = true;
+ public static boolean sUseRoundIcon = false;
+
+ public static final int PARSE_DEFAULT_INSTALL_LOCATION =
+ PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ public static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
+
+ public static final int PARSE_MUST_BE_APK = 1 << 0;
+ public static final int PARSE_IGNORE_PROCESSES = 1 << 1;
+ public static final int PARSE_EXTERNAL_STORAGE = 1 << 3;
+ public static final int PARSE_IS_SYSTEM_DIR = 1 << 4;
+ public static final int PARSE_COLLECT_CERTIFICATES = 1 << 5;
+ public static final int PARSE_ENFORCE_CODE = 1 << 6;
+ public static final int PARSE_CHATTY = 1 << 31;
+
+ @IntDef(flag = true, prefix = { "PARSE_" }, value = {
+ PARSE_CHATTY,
+ PARSE_COLLECT_CERTIFICATES,
+ PARSE_ENFORCE_CODE,
+ PARSE_EXTERNAL_STORAGE,
+ PARSE_IGNORE_PROCESSES,
+ PARSE_IS_SYSTEM_DIR,
+ PARSE_MUST_BE_APK,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ParseFlags {}
+
/**
* For those names would be used as a part of the file name. Limits size to 223 and reserves 32
* for the OS.
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
index 0d7198d..f96bd54 100644
--- a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.app.ActivityTaskManager;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageParser;
import android.content.pm.parsing.ParsingPackage;
@@ -33,6 +34,7 @@
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.os.Build;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -50,12 +52,21 @@
import java.io.IOException;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/** @hide */
public class ParsedActivityUtils {
private static final String TAG = ParsingUtils.TAG;
+ public static final boolean LOG_UNSAFE_BROADCASTS = false;
+
+ // Set of broadcast actions that are safe for manifest receivers
+ public static final Set<String> SAFE_BROADCASTS = new ArraySet<>();
+ static {
+ SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED);
+ }
+
@NonNull
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public static ParseResult<ParsedActivity> parseActivityOrReceiver(String[] separateProcesses,
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
index c0536bb..368dcfd 100644
--- a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
@@ -44,6 +44,8 @@
private static final String TAG = ParsingUtils.TAG;
+ public static final boolean DEBUG = false;
+
@NonNull
public static ParseResult<ParsedIntentInfo> parseIntentInfo(String className,
ParsingPackage pkg, Resources res, XmlResourceParser parser, boolean allowGlobs,
@@ -209,6 +211,25 @@
PatternMatcher.PATTERN_SIMPLE_GLOB);
}
+ str = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestData_sspAdvancedPattern, 0);
+ if (str != null) {
+ if (!allowGlobs) {
+ return input.error(
+ "sspAdvancedPattern not allowed here; ssp must be literal");
+ }
+ intentInfo.addDataSchemeSpecificPart(str,
+ PatternMatcher.PATTERN_ADVANCED_GLOB);
+ }
+
+ str = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestData_sspSuffix, 0);
+ if (str != null) {
+ intentInfo.addDataSchemeSpecificPart(str,
+ PatternMatcher.PATTERN_SUFFIX);
+ }
+
+
String host = sa.getNonConfigurationString(
R.styleable.AndroidManifestData_host, 0);
String port = sa.getNonConfigurationString(
@@ -249,6 +270,13 @@
intentInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
}
+ str = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestData_pathSuffix, 0);
+ if (str != null) {
+ intentInfo.addDataPath(str, PatternMatcher.PATTERN_SUFFIX);
+ }
+
+
return input.success(null);
} finally {
sa.recycle();
diff --git a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
index 90691f1..4deab56 100644
--- a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
+++ b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
@@ -211,22 +211,34 @@
R.styleable.AndroidManifestGrantUriPermission);
try {
String name = parser.getName();
- // Pattern has priority over prefix over literal path
+ // Pattern has priority over pre/suffix over literal path
PatternMatcher pa = null;
String str = sa.getNonConfigurationString(
- R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
+ R.styleable.AndroidManifestGrantUriPermission_pathAdvancedPattern, 0);
if (str != null) {
- pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
+ pa = new PatternMatcher(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
} else {
str = sa.getNonConfigurationString(
- R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
+ R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
if (str != null) {
- pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
+ pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
} else {
str = sa.getNonConfigurationString(
- R.styleable.AndroidManifestGrantUriPermission_path, 0);
+ R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
if (str != null) {
- pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
+ pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
+ } else {
+ str = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestGrantUriPermission_pathSuffix, 0);
+ if (str != null) {
+ pa = new PatternMatcher(str, PatternMatcher.PATTERN_SUFFIX);
+ } else {
+ str = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestGrantUriPermission_path, 0);
+ if (str != null) {
+ pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
+ }
+ }
}
}
}
@@ -318,10 +330,18 @@
pa = new PathPermission(path, PatternMatcher.PATTERN_PREFIX, readPermission,
writePermission);
} else {
- path = sa.getNonConfigurationString(R.styleable.AndroidManifestPathPermission_path, 0);
+ path = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestPathPermission_pathSuffix, 0);
if (path != null) {
- pa = new PathPermission(path, PatternMatcher.PATTERN_LITERAL,
+ pa = new PathPermission(path, PatternMatcher.PATTERN_SUFFIX,
readPermission, writePermission);
+ } else {
+ path = sa.getNonConfigurationString(
+ R.styleable.AndroidManifestPathPermission_path, 0);
+ if (path != null) {
+ pa = new PathPermission(path, PatternMatcher.PATTERN_LITERAL,
+ readPermission, writePermission);
+ }
}
}
}
diff --git a/core/java/android/hardware/CameraStreamStats.java b/core/java/android/hardware/CameraStreamStats.java
index ae801b6..41d1e25 100644
--- a/core/java/android/hardware/CameraStreamStats.java
+++ b/core/java/android/hardware/CameraStreamStats.java
@@ -19,7 +19,6 @@
import android.os.Parcelable;
import android.util.Log;
-import java.util.ArrayList;
/**
* The camera stream statistics used for passing camera stream information from
* camera service to camera service proxy.
@@ -30,6 +29,8 @@
* @hide
*/
public class CameraStreamStats implements Parcelable {
+ public static final int HISTOGRAM_TYPE_UNKNOWN = 0;
+ public static final int HISTOGRAM_TYPE_CAPTURE_LATENCY = 1;
private int mWidth;
private int mHeight;
@@ -41,6 +42,9 @@
private int mStartLatencyMs;
private int mMaxHalBuffers;
private int mMaxAppBuffers;
+ private int mHistogramType;
+ private float[] mHistogramBins;
+ private long[] mHistogramCounts;
private static final String TAG = "CameraStreamStats";
@@ -55,6 +59,7 @@
mStartLatencyMs = 0;
mMaxHalBuffers = 0;
mMaxAppBuffers = 0;
+ mHistogramType = HISTOGRAM_TYPE_UNKNOWN;
}
public CameraStreamStats(int width, int height, int format,
@@ -70,6 +75,7 @@
mStartLatencyMs = startLatencyMs;
mMaxHalBuffers = maxHalBuffers;
mMaxAppBuffers = maxAppBuffers;
+ mHistogramType = HISTOGRAM_TYPE_UNKNOWN;
}
public static final @android.annotation.NonNull Parcelable.Creator<CameraStreamStats> CREATOR =
@@ -112,6 +118,9 @@
dest.writeInt(mStartLatencyMs);
dest.writeInt(mMaxHalBuffers);
dest.writeInt(mMaxAppBuffers);
+ dest.writeInt(mHistogramType);
+ dest.writeFloatArray(mHistogramBins);
+ dest.writeLongArray(mHistogramCounts);
}
public void readFromParcel(Parcel in) {
@@ -125,6 +134,9 @@
mStartLatencyMs = in.readInt();
mMaxHalBuffers = in.readInt();
mMaxAppBuffers = in.readInt();
+ mHistogramType = in.readInt();
+ mHistogramBins = in.createFloatArray();
+ mHistogramCounts = in.createLongArray();
}
public int getWidth() {
@@ -166,4 +178,16 @@
public int getMaxAppBuffers() {
return mMaxAppBuffers;
}
+
+ public int getHistogramType() {
+ return mHistogramType;
+ }
+
+ public float[] getHistogramBins() {
+ return mHistogramBins;
+ }
+
+ public long[] getHistogramCounts() {
+ return mHistogramCounts;
+ }
}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index f7c4c2c..ec6c233 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -881,7 +881,11 @@
}
}
- static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) {
+ /**
+ * Return sensor's maximum length of values array
+ * @hide
+ */
+ public static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) {
// RotationVector length has changed to 3 to 5 for API level 18
// Set it to 3 for backward compatibility.
if (sensor.mType == Sensor.TYPE_ROTATION_VECTOR
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index 8497525..e165ad6 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
@@ -40,14 +41,19 @@
*
* @hide
*/
+@TestApi
@SystemService(Context.SENSOR_PRIVACY_SERVICE)
public final class SensorPrivacyManager {
- /** Microphone */
+ /** Microphone
+ * @hide */
+ @TestApi
public static final int INDIVIDUAL_SENSOR_MICROPHONE =
SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
- /** Camera */
+ /** Camera
+ * @hide */
+ @TestApi
public static final int INDIVIDUAL_SENSOR_CAMERA =
SensorPrivacyIndividualEnabledSensorProto.CAMERA;
@@ -66,6 +72,8 @@
* A class implementing this interface can register with the {@link
* android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy
* state changes.
+ *
+ * @hide
*/
public interface OnSensorPrivacyChangedListener {
/**
@@ -101,6 +109,8 @@
/**
* Returns the single instance of the SensorPrivacyManager.
+ *
+ * @hide
*/
public static SensorPrivacyManager getInstance(Context context) {
synchronized (sInstanceLock) {
@@ -121,6 +131,8 @@
* Sets sensor privacy to the specified state.
*
* @param enable the state to which sensor privacy should be set.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setSensorPrivacy(boolean enable) {
@@ -137,6 +149,8 @@
*
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
* privacy changes.
+ *
+ * @hide
*/
public void addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) {
@@ -166,6 +180,8 @@
* @param sensor the sensor to listen to changes to
* @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
* privacy changes.
+ *
+ * @hide
*/
public void addSensorPrivacyListener(@IndividualSensor int sensor,
final OnSensorPrivacyChangedListener listener) {
@@ -196,6 +212,8 @@
*
* @param listener the OnSensorPrivacyChangedListener to be unregistered from notifications when
* sensor privacy changes.
+ *
+ * @hide
*/
public void removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) {
@@ -215,6 +233,8 @@
* Returns whether sensor privacy is currently enabled.
*
* @return true if sensor privacy is currently enabled, false otherwise.
+ *
+ * @hide
*/
public boolean isSensorPrivacyEnabled() {
try {
@@ -228,7 +248,10 @@
* Returns whether sensor privacy is currently enabled for a specific sensor.
*
* @return true if sensor privacy is currently enabled, false otherwise.
+ *
+ * @hide
*/
+ @TestApi
public boolean isIndividualSensorPrivacyEnabled(@IndividualSensor int sensor) {
try {
return mService.isIndividualSensorPrivacyEnabled(mContext.getUserId(), sensor);
@@ -242,7 +265,10 @@
*
* @param sensor the sensor which to change the state for
* @param enable the state to which sensor privacy should be set.
+ *
+ * @hide
*/
+ @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setIndividualSensorPrivacy(@IndividualSensor int sensor,
boolean enable) {
@@ -259,7 +285,10 @@
*
* @param sensor the sensor which to change the state for
* @param enable the state to which sensor privacy should be set.
+ *
+ * @hide
*/
+ @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
public void setIndividualSensorPrivacyForProfileGroup(@IndividualSensor int sensor,
boolean enable) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
index 3a9d143..2650dc5 100644
--- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
+++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java
@@ -84,7 +84,7 @@
// TODO: Value should be provided from the HAL
this(sensorId, strength, maxEnrollmentsPerUser, sensorType,
resetLockoutRequiresHardwareAuthToken, 540 /* sensorLocationX */,
- 1636 /* sensorLocationY */, 130 /* sensorRadius */);
+ 1769 /* sensorLocationY */, 130 /* sensorRadius */);
}
protected FingerprintSensorPropertiesInternal(Parcel in) {
diff --git a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
index 58b7046..aced9c7 100644
--- a/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
+++ b/core/java/android/hardware/fingerprint/IUdfpsOverlayController.aidl
@@ -20,8 +20,12 @@
* @hide
*/
oneway interface IUdfpsOverlayController {
+ const int REASON_UNKNOWN = 0;
+ const int REASON_ENROLL = 1;
+ const int REASON_AUTH = 2;
+
// Shows the overlay.
- void showUdfpsOverlay(int sensorId);
+ void showUdfpsOverlay(int sensorId, int reason);
// Hides the overlay.
void hideUdfpsOverlay(int sensorId);
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 43f04cd..b09eda4 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -327,17 +327,19 @@
*
* @hide
*/
+ @SystemApi
public static final int HDMI_CEC_CONTROL_ENABLED = 1;
/**
* HDMI CEC disabled.
*
* @hide
*/
+ @SystemApi
public static final int HDMI_CEC_CONTROL_DISABLED = 0;
/**
* @hide
*/
- @IntDef({
+ @IntDef(prefix = { "HDMI_CEC_CONTROL_" }, value = {
HDMI_CEC_CONTROL_ENABLED,
HDMI_CEC_CONTROL_DISABLED
})
@@ -350,17 +352,19 @@
*
* @hide
*/
+ @SystemApi
public static final int HDMI_CEC_VERSION_1_4_B = 0x05;
/**
* Version constant for HDMI-CEC v2.0.
*
* @hide
*/
+ @SystemApi
public static final int HDMI_CEC_VERSION_2_0 = 0x06;
/**
* @hide
*/
- @IntDef({
+ @IntDef(prefix = { "HDMI_CEC_VERSION_" }, value = {
HDMI_CEC_VERSION_1_4_B,
HDMI_CEC_VERSION_2_0
})
@@ -373,23 +377,26 @@
*
* @hide
*/
+ @SystemApi
public static final String POWER_CONTROL_MODE_TV = "to_tv";
/**
* Broadcast CEC power control messages to all devices in the network.
*
* @hide
*/
+ @SystemApi
public static final String POWER_CONTROL_MODE_BROADCAST = "broadcast";
/**
* Don't send any CEC power control messages.
*
* @hide
*/
+ @SystemApi
public static final String POWER_CONTROL_MODE_NONE = "none";
/**
* @hide
*/
- @StringDef({
+ @StringDef(prefix = { "POWER_CONTROL_MODE_" }, value = {
POWER_CONTROL_MODE_TV,
POWER_CONTROL_MODE_BROADCAST,
POWER_CONTROL_MODE_NONE
@@ -403,17 +410,19 @@
*
* @hide
*/
+ @SystemApi
public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE = "none";
/**
* Go to standby immediately.
*
* @hide
*/
+ @SystemApi
public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW = "standby_now";
/**
* @hide
*/
- @StringDef({
+ @StringDef(prefix = { "POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_" }, value = {
POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE,
POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW
})
@@ -426,17 +435,19 @@
*
* @hide
*/
+ @SystemApi
public static final int SYSTEM_AUDIO_MODE_MUTING_ENABLED = 1;
/**
* System Audio Mode muting disabled.
*
* @hide
*/
+ @SystemApi
public static final int SYSTEM_AUDIO_MODE_MUTING_DISABLED = 0;
/**
* @hide
*/
- @IntDef({
+ @IntDef(prefix = { "SYSTEM_AUDIO_MODE_MUTING_" }, value = {
SYSTEM_AUDIO_MODE_MUTING_ENABLED,
SYSTEM_AUDIO_MODE_MUTING_DISABLED
})
@@ -449,24 +460,28 @@
*
* @hide
*/
+ @SystemApi
public static final String CEC_SETTING_NAME_HDMI_CEC_ENABLED = "hdmi_cec_enabled";
/**
* Name of a setting controlling the version of HDMI-CEC used.
*
* @hide
*/
+ @SystemApi
public static final String CEC_SETTING_NAME_HDMI_CEC_VERSION = "hdmi_cec_version";
/**
* Name of a setting deciding on the power control mode.
*
* @hide
*/
+ @SystemApi
public static final String CEC_SETTING_NAME_POWER_CONTROL_MODE = "send_standby_on_sleep";
/**
* Name of a setting deciding on power state action when losing Active Source.
*
* @hide
*/
+ @SystemApi
public static final String CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST =
"power_state_change_on_active_source_lost";
/**
@@ -474,12 +489,13 @@
*
* @hide
*/
+ @SystemApi
public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING =
"system_audio_mode_muting";
/**
* @hide
*/
- @StringDef({
+ @StringDef(prefix = { "CEC_SETTING_NAME_" }, value = {
CEC_SETTING_NAME_HDMI_CEC_ENABLED,
CEC_SETTING_NAME_HDMI_CEC_VERSION,
CEC_SETTING_NAME_POWER_CONTROL_MODE,
@@ -1356,6 +1372,87 @@
}
/**
+ * Listener used to get setting change notification.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface CecSettingChangeListener {
+ /**
+ * Called when value of a setting changes.
+ *
+ * @param setting name of a CEC setting that changed
+ */
+ void onChange(@NonNull @CecSettingName String setting);
+ }
+
+ private final ArrayMap<String,
+ ArrayMap<CecSettingChangeListener, IHdmiCecSettingChangeListener>>
+ mCecSettingChangeListeners = new ArrayMap<>();
+
+ private void addCecSettingChangeListener(
+ @NonNull @CecSettingName String setting,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull CecSettingChangeListener listener) {
+ if (mService == null) {
+ Log.e(TAG, "HdmiControlService is not available");
+ return;
+ }
+ if (mCecSettingChangeListeners.containsKey(setting)
+ && mCecSettingChangeListeners.get(setting).containsKey(listener)) {
+ Log.e(TAG, "listener is already registered");
+ return;
+ }
+ IHdmiCecSettingChangeListener wrappedListener =
+ getCecSettingChangeListenerWrapper(executor, listener);
+ if (!mCecSettingChangeListeners.containsKey(setting)) {
+ mCecSettingChangeListeners.put(setting, new ArrayMap<>());
+ }
+ mCecSettingChangeListeners.get(setting).put(listener, wrappedListener);
+ try {
+ mService.addCecSettingChangeListener(setting, wrappedListener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private void removeCecSettingChangeListener(
+ @NonNull @CecSettingName String setting,
+ @NonNull CecSettingChangeListener listener) {
+ if (mService == null) {
+ Log.e(TAG, "HdmiControlService is not available");
+ return;
+ }
+ IHdmiCecSettingChangeListener wrappedListener =
+ !mCecSettingChangeListeners.containsKey(setting) ? null :
+ mCecSettingChangeListeners.get(setting).remove(listener);
+ if (wrappedListener == null) {
+ Log.e(TAG, "tried to remove not-registered listener");
+ return;
+ }
+ try {
+ mService.removeCecSettingChangeListener(setting, wrappedListener);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private IHdmiCecSettingChangeListener getCecSettingChangeListenerWrapper(
+ Executor executor, final CecSettingChangeListener listener) {
+ return new IHdmiCecSettingChangeListener.Stub() {
+ @Override
+ public void onChange(String setting) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> listener.onChange(setting));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+ }
+
+ /**
* Get a set of user-modifiable settings.
*
* @return a set of user-modifiable settings.
@@ -1363,6 +1460,7 @@
*
* @hide
*/
+ @SystemApi
@NonNull
@CecSettingName
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
@@ -1389,6 +1487,7 @@
*
* @hide
*/
+ @SystemApi
@NonNull
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public List<String> getAllowedCecSettingStringValues(@NonNull @CecSettingName String name) {
@@ -1414,6 +1513,7 @@
*
* @hide
*/
+ @SystemApi
@NonNull
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public List<Integer> getAllowedCecSettingIntValues(@NonNull @CecSettingName String name) {
@@ -1430,14 +1530,13 @@
}
/**
- * Set the 'hdmi_cec_enabled' option.
+ * Set the global status of HDMI CEC.
*
- * @param value the desired value
- * @throws IllegalArgumentException when the new value is not allowed.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>This allows to enable/disable HDMI CEC on the device.
*
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void setHdmiCecEnabled(@NonNull @HdmiCecControl int value) {
if (mService == null) {
@@ -1452,13 +1551,13 @@
}
/**
- * Get the value of 'hdmi_cec_enabled' option.
+ * Get the current global status of HDMI CEC.
*
- * @return the current value.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>Reflects whether HDMI CEC is currently enabled on the device.
*
* @hide
*/
+ @SystemApi
@NonNull
@HdmiCecControl
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
@@ -1475,14 +1574,60 @@
}
/**
- * Set the 'hdmi_cec_version' option.
+ * Add change listener for global status of HDMI CEC.
*
- * @param value the desired value
- * @throws IllegalArgumentException when the new value is not allowed.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>To stop getting the notification,
+ * use {@link #removeHdmiCecEnabledChangeListener(CecSettingChangeListener)}.
+ *
+ * Note that each invocation of the callback will be executed on an arbitrary
+ * Binder thread. This means that all callback implementations must be
+ * thread safe. To specify the execution thread, use
+ * {@link addHdmiCecEnabledChangeListener(Executor, CecSettingChangeListener)}.
*
* @hide
*/
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.HDMI_CEC)
+ public void addHdmiCecEnabledChangeListener(@NonNull CecSettingChangeListener listener) {
+ addHdmiCecEnabledChangeListener(ConcurrentUtils.DIRECT_EXECUTOR, listener);
+ }
+
+ /**
+ * Add change listener for global status of HDMI CEC.
+ *
+ * <p>To stop getting the notification,
+ * use {@link #removeHdmiCecEnabledChangeListener(CecSettingChangeListener)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.HDMI_CEC)
+ public void addHdmiCecEnabledChangeListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull CecSettingChangeListener listener) {
+ addCecSettingChangeListener(CEC_SETTING_NAME_HDMI_CEC_ENABLED, executor, listener);
+ }
+
+ /**
+ * Remove change listener for global status of HDMI CEC.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.HDMI_CEC)
+ public void removeHdmiCecEnabledChangeListener(
+ @NonNull CecSettingChangeListener listener) {
+ removeCecSettingChangeListener(CEC_SETTING_NAME_HDMI_CEC_ENABLED, listener);
+ }
+
+ /**
+ * Set the version of the HDMI CEC specification currently used.
+ *
+ * <p>Allows to select either CEC 1.4b or 2.0 to be used by the device.
+ *
+ * @hide
+ */
+ @SystemApi
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void setHdmiCecVersion(@NonNull @HdmiCecVersion int value) {
if (mService == null) {
@@ -1497,13 +1642,13 @@
}
/**
- * Get the value of 'hdmi_cec_enabled' option.
+ * Get the version of the HDMI CEC specification currently used.
*
- * @return the current value.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>Reflects which CEC version 1.4b or 2.0 is currently used by the device.
*
* @hide
*/
+ @SystemApi
@NonNull
@HdmiCecVersion
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
@@ -1520,14 +1665,14 @@
}
/**
- * Set the 'power_control_mode' option.
+ * Set the status of Power Control.
*
- * @param value the desired value
- * @throws IllegalArgumentException when the new value is not allowed.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>Specifies to which devices Power Control messages should be sent:
+ * only to the TV, broadcast to all devices, no power control messages.
*
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void setPowerControlMode(@NonNull @PowerControlMode String value) {
if (mService == null) {
@@ -1542,13 +1687,14 @@
}
/**
- * Get the value of 'power_control_mode' option.
+ * Get the status of Power Control.
*
- * @return the current value.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>Reflects to which devices Power Control messages should be sent:
+ * only to the TV, broadcast to all devices, no power control messages.
*
* @hide
*/
+ @SystemApi
@NonNull
@PowerControlMode
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
@@ -1565,14 +1711,13 @@
}
/**
- * Set the 'power_state_change_on_active_source_lost' option.
+ * Set the current power state behaviour when Active Source is lost.
*
- * @param value the desired value
- * @throws IllegalArgumentException when the new value is not allowed
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>Sets the action taken: do nothing or go to sleep immediately.
*
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void setPowerStateChangeOnActiveSourceLost(
@NonNull @ActiveSourceLostBehavior String value) {
@@ -1589,13 +1734,13 @@
}
/**
- * Get the value of 'power_state_change_on_active_source_lost' option.
+ * Get the current power state behaviour when Active Source is lost.
*
- * @return the current value.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>Reflects the action taken: do nothing or go to sleep immediately.
*
* @hide
*/
+ @SystemApi
@NonNull
@ActiveSourceLostBehavior
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
@@ -1613,14 +1758,13 @@
}
/**
- * Set the 'system_audio_mode_muting' option.
+ * Set the current status of System Audio Mode muting.
*
- * @param value the desired value
- * @throws IllegalArgumentException when the new value is not allowed.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>Sets whether the device should be muted when System Audio Mode is turned off.
*
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
public void setSystemAudioModeMuting(@NonNull @SystemAudioModeMuting int value) {
if (mService == null) {
@@ -1635,13 +1779,13 @@
}
/**
- * Get the value of 'system_audio_mode_muting' option.
+ * Get the current status of System Audio Mode muting.
*
- * @return the current value.
- * @throws RuntimeException when the HdmiControlService is not available.
+ * <p>Reflects whether the device should be muted when System Audio Mode is turned off.
*
* @hide
*/
+ @SystemApi
@NonNull
@SystemAudioModeMuting
@RequiresPermission(android.Manifest.permission.HDMI_CEC)
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index 3b61911f..89a7afa8 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -306,6 +306,18 @@
}
@Override
+ public void addCecSettingChangeListener(String name,
+ IHdmiCecSettingChangeListener listener) {
+ HdmiControlServiceWrapper.this.addCecSettingChangeListener(name, listener);
+ }
+
+ @Override
+ public void removeCecSettingChangeListener(String name,
+ IHdmiCecSettingChangeListener listener) {
+ HdmiControlServiceWrapper.this.removeCecSettingChangeListener(name, listener);
+ }
+
+ @Override
public List<String> getUserCecSettings() {
return HdmiControlServiceWrapper.this.getUserCecSettings();
}
@@ -522,6 +534,14 @@
IHdmiCecVolumeControlFeatureListener listener) {}
/** @hide */
+ public void addCecSettingChangeListener(String name,
+ IHdmiCecSettingChangeListener listener) {}
+
+ /** @hide */
+ public void removeCecSettingChangeListener(String name,
+ IHdmiCecSettingChangeListener listener) {}
+
+ /** @hide */
public List<String> getUserCecSettings() {
return new ArrayList<>();
}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl b/core/java/android/hardware/hdmi/IHdmiCecSettingChangeListener.aidl
similarity index 68%
copy from media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
copy to core/java/android/hardware/hdmi/IHdmiCecSettingChangeListener.aidl
index 919a215..6f7a6f8 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiCecSettingChangeListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,11 +14,14 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.hardware.hdmi;
/**
- * Information required to request a Tuner Demux.
+ * Callback interface definition for HDMI client to get informed of
+ * CEC setting change.
*
* @hide
*/
-parcelable TunerDemuxRequest;
\ No newline at end of file
+oneway interface IHdmiCecSettingChangeListener {
+ void onChange(in String setting);
+}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 65bd856..d7329e0 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -18,6 +18,7 @@
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiPortInfo;
+import android.hardware.hdmi.IHdmiCecSettingChangeListener;
import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.hdmi.IHdmiControlStatusChangeListener;
@@ -89,6 +90,8 @@
boolean isHdmiCecVolumeControlEnabled();
void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
void setSystemAudioModeOnForAudioOnlySource();
+ void addCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener);
+ void removeCecSettingChangeListener(String name, IHdmiCecSettingChangeListener listener);
List<String> getUserCecSettings();
List<String> getAllowedCecSettingStringValues(String name);
int[] getAllowedCecSettingIntValues(String name);
diff --git a/core/java/android/hardware/input/InputDeviceSensorManager.java b/core/java/android/hardware/input/InputDeviceSensorManager.java
index 56c2cdd..89db857 100644
--- a/core/java/android/hardware/input/InputDeviceSensorManager.java
+++ b/core/java/android/hardware/input/InputDeviceSensorManager.java
@@ -25,6 +25,7 @@
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.TriggerEventListener;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -32,6 +33,7 @@
import android.os.Message;
import android.os.RemoteException;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.InputDevice;
import com.android.internal.annotations.GuardedBy;
@@ -65,8 +67,8 @@
@GuardedBy("mInputSensorLock")
private final ArrayList<InputSensorEventListenerDelegate> mInputSensorEventListeners =
new ArrayList<InputSensorEventListenerDelegate>();
- private HandlerThread mSensorThread = null;
- private Handler mSensorHandler = null;
+ private final HandlerThread mSensorThread;
+ private final Handler mSensorHandler;
public InputDeviceSensorManager(InputManager inputManager) {
mInputManager = inputManager;
@@ -125,9 +127,7 @@
@Override
public void onInputDeviceChanged(int deviceId) {
synchronized (mInputSensorLock) {
- if (mSensors.containsKey(deviceId)) {
- mSensors.remove(deviceId);
- }
+ mSensors.remove(deviceId);
updateInputDeviceSensorInfoLocked(deviceId);
}
}
@@ -196,16 +196,21 @@
+ " timestamp=" + timestamp + " sensorType=" + sensorType);
}
synchronized (mInputSensorLock) {
- SensorEvent event = createSensorEvent(
- InputDevice.getDevice(deviceId), sensorType, accuracy, timestamp, values);
- if (event == null) {
- Slog.wtf(TAG, "Failed to create SensorEvent.");
- return;
- }
+ Sensor sensor = getInputDeviceSensorLocked(deviceId, sensorType);
for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
InputSensorEventListenerDelegate listener =
mInputSensorEventListeners.get(i);
if (listener.hasSensorRegistered(deviceId, sensorType)) {
+ SensorEvent event = listener.getSensorEvent(sensor);
+ if (event == null) {
+ Slog.wtf(TAG, "Failed to get SensorEvent.");
+ return;
+ }
+ event.sensor = sensor;
+ event.accuracy = accuracy;
+ event.timestamp = timestamp;
+ System.arraycopy(values, 0, event.values, 0, event.values.length);
+ // Call listener for sensor changed
listener.sendSensorChanged(event);
}
}
@@ -249,15 +254,19 @@
private final SensorEventListener mListener;
private final int mDelayUs;
private final int mMaxBatchReportLatencyUs;
+ // List of sensors being listened to
private List<Sensor> mSensors = new ArrayList<Sensor>();
+ // Sensor event array by sensor type, preallocate sensor events for each sensor of listener
+ // to avoid allocation and garbage collection for each listener callback.
+ private final SparseArray<SensorEvent> mSensorEvents = new SparseArray<SensorEvent>();
InputSensorEventListenerDelegate(SensorEventListener listener, Sensor sensor,
int delayUs, int maxBatchReportLatencyUs, Handler handler) {
super(handler != null ? handler.getLooper() : Looper.myLooper());
mListener = listener;
- mSensors.add(sensor);
mDelayUs = delayUs;
mMaxBatchReportLatencyUs = maxBatchReportLatencyUs;
+ addSensor(sensor);
}
public List<Sensor> getSensors() {
@@ -276,10 +285,12 @@
// and the sensor list is cleared.
if (sensor == null) {
mSensors.clear();
+ mSensorEvents.clear();
}
for (Sensor s : mSensors) {
if (sensorEquals(s, sensor)) {
mSensors.remove(sensor);
+ mSensorEvents.remove(sensor.getType());
}
}
}
@@ -295,6 +306,10 @@
}
}
mSensors.add(sensor);
+ final int vecLength = sensor.getMaxLengthValuesArray(sensor, Build.VERSION.SDK_INT);
+ SensorEvent event = new SensorEvent(sensor, SensorManager.SENSOR_STATUS_NO_CONTACT,
+ 0 /* timestamp */, new float[vecLength]);
+ mSensorEvents.put(sensor.getType(), event);
}
/**
@@ -320,6 +335,13 @@
}
/**
+ * Get SensorEvent object for input device, with specified sensor.
+ */
+ private SensorEvent getSensorEvent(@NonNull Sensor sensor) {
+ return mSensorEvents.get(sensor.getType());
+ }
+
+ /**
* Send sensor changed message
*/
public void sendSensorChanged(SensorEvent event) {
@@ -360,26 +382,6 @@
}
/**
- * Create SensorEvent object for input device, with specified device ID, sensor Type,
- * sensor event timestamp, accuracy, and sensor values.
- */
- private SensorEvent createSensorEvent(InputDevice inputDevice, int sensorType, int accuracy,
- long timestamp, float[] values) {
- synchronized (mInputSensorLock) {
- Sensor sensor = getInputDeviceSensorLocked(inputDevice.getId(), sensorType);
- if (sensor == null) {
- Slog.wtf(TAG, "Can't get sensor type " + sensorType + " for input device "
- + inputDevice);
- }
- SensorEvent event = new SensorEvent(sensor, accuracy, timestamp, values);
- if (event == null) {
- Slog.wtf(TAG, "Failed to create SensorEvent.");
- }
- return event;
- }
- }
-
- /**
* Return the default sensor object for input device, for specific sensor type.
*/
private Sensor getSensorForInputDevice(int deviceId, int type) {
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 9d20f6d..6ab1106 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -201,8 +201,6 @@
* Prevent touches from being consumed by apps if these touches passed through a non-trusted
* window from a different UID and are considered unsafe.
*
- * TODO(b/158002302): Turn the feature on by default
- *
* @hide
*/
@TestApi
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index a4f88af..899af5a 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -16,6 +16,9 @@
package android.net;
import static android.net.IpSecManager.INVALID_RESOURCE_ID;
+import static android.net.NetworkRequest.Type.LISTEN;
+import static android.net.NetworkRequest.Type.REQUEST;
+import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
@@ -69,7 +72,6 @@
import libcore.net.event.NetworkEventDispatcher;
-import java.io.FileDescriptor;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.annotation.Retention;
@@ -1955,6 +1957,12 @@
return k;
}
+ // Construct an invalid fd.
+ private ParcelFileDescriptor createInvalidFd() {
+ final int invalidFd = -1;
+ return ParcelFileDescriptor.adoptFd(invalidFd);
+ }
+
/**
* Request that keepalives be started on a IPsec NAT-T socket.
*
@@ -1985,7 +1993,7 @@
} catch (IOException ignored) {
// Construct an invalid fd, so that if the user later calls start(), it will fail with
// ERROR_INVALID_SOCKET.
- dup = new ParcelFileDescriptor(new FileDescriptor());
+ dup = createInvalidFd();
}
return new NattSocketKeepalive(mService, network, dup, socket.getResourceId(), source,
destination, executor, callback);
@@ -2027,7 +2035,7 @@
} catch (IOException ignored) {
// Construct an invalid fd, so that if the user later calls start(), it will fail with
// ERROR_INVALID_SOCKET.
- dup = new ParcelFileDescriptor(new FileDescriptor());
+ dup = createInvalidFd();
}
return new NattSocketKeepalive(mService, network, dup,
INVALID_RESOURCE_ID /* Unused */, source, destination, executor, callback);
@@ -2064,7 +2072,7 @@
} catch (UncheckedIOException ignored) {
// Construct an invalid fd, so that if the user later calls start(), it will fail with
// ERROR_INVALID_SOCKET.
- dup = new ParcelFileDescriptor(new FileDescriptor());
+ dup = createInvalidFd();
}
return new TcpSocketKeepalive(mService, network, dup, executor, callback);
}
@@ -3730,14 +3738,12 @@
private static final HashMap<NetworkRequest, NetworkCallback> sCallbacks = new HashMap<>();
private static CallbackHandler sCallbackHandler;
- private static final int LISTEN = 1;
- private static final int REQUEST = 2;
-
private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
- int timeoutMs, int action, int legacyType, CallbackHandler handler) {
+ int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) {
printStackTrace();
checkCallbackNotNull(callback);
- Preconditions.checkArgument(action == REQUEST || need != null, "null NetworkCapabilities");
+ Preconditions.checkArgument(
+ reqType == TRACK_DEFAULT || need != null, "null NetworkCapabilities");
final NetworkRequest request;
final String callingPackageName = mContext.getOpPackageName();
try {
@@ -3750,13 +3756,13 @@
}
Messenger messenger = new Messenger(handler);
Binder binder = new Binder();
- if (action == LISTEN) {
+ if (reqType == LISTEN) {
request = mService.listenForNetwork(
need, messenger, binder, callingPackageName);
} else {
request = mService.requestNetwork(
- need, messenger, timeoutMs, binder, legacyType, callingPackageName,
- getAttributionTag());
+ need, reqType.ordinal(), messenger, timeoutMs, binder, legacyType,
+ callingPackageName, getAttributionTag());
}
if (request != null) {
sCallbacks.put(request, callback);
@@ -4260,7 +4266,7 @@
// request, i.e., the system default network.
CallbackHandler cbHandler = new CallbackHandler(handler);
sendRequestForNetwork(null /* NetworkCapabilities need */, networkCallback, 0,
- REQUEST, TYPE_NONE, cbHandler);
+ TRACK_DEFAULT, TYPE_NONE, cbHandler);
}
/**
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b32c98b..5e925b6 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -167,7 +167,7 @@
in NetworkCapabilities nc, int score, in NetworkAgentConfig config,
in int factorySerialNumber);
- NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
+ NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, int reqType,
in Messenger messenger, int timeoutSec, in IBinder binder, int legacy,
String callingPackageName, String callingAttributionTag);
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index 37813ce..0a6be20 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -85,14 +85,14 @@
/**
* Interface data activity status is changed.
*
- * @param networkType The legacy network type of the data activity change.
+ * @param transportType The transport type of the data activity change.
* @param active True if the interface is actively transmitting data, false if it is idle.
* @param tsNanos Elapsed realtime in nanos when the state of the network interface changed.
* @param uid Uid of this event. It represents the uid that was responsible for waking the
* radio. For those events that are reported by system itself, not from specific uid,
* use -1 for the events which means no uid.
*/
- void interfaceClassDataActivityChanged(int networkType, boolean active, long tsNanos, int uid);
+ void interfaceClassDataActivityChanged(int transportType, boolean active, long tsNanos, int uid);
/**
* Information about available DNS servers has been received.
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index b779636..2d9f6d8 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -469,10 +469,10 @@
*/
@VisibleForTesting
/* package */ static final long UNRESTRICTED_CAPABILITIES =
- (1 << NET_CAPABILITY_INTERNET) |
- (1 << NET_CAPABILITY_MMS) |
- (1 << NET_CAPABILITY_SUPL) |
- (1 << NET_CAPABILITY_WIFI_P2P);
+ (1 << NET_CAPABILITY_INTERNET)
+ | (1 << NET_CAPABILITY_MMS)
+ | (1 << NET_CAPABILITY_SUPL)
+ | (1 << NET_CAPABILITY_WIFI_P2P);
/**
* Capabilities that are managed by ConnectivityService.
@@ -940,8 +940,8 @@
}
private boolean satisfiedByTransportTypes(NetworkCapabilities nc) {
- return ((this.mTransportTypes == 0) ||
- ((this.mTransportTypes & nc.mTransportTypes) != 0));
+ return ((this.mTransportTypes == 0)
+ || ((this.mTransportTypes & nc.mTransportTypes) != 0));
}
/** @hide */
@@ -1195,12 +1195,12 @@
Math.max(this.mLinkDownBandwidthKbps, nc.mLinkDownBandwidthKbps);
}
private boolean satisfiedByLinkBandwidths(NetworkCapabilities nc) {
- return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps ||
- this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps);
+ return !(this.mLinkUpBandwidthKbps > nc.mLinkUpBandwidthKbps
+ || this.mLinkDownBandwidthKbps > nc.mLinkDownBandwidthKbps);
}
private boolean equalsLinkBandwidths(NetworkCapabilities nc) {
- return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps &&
- this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
+ return (this.mLinkUpBandwidthKbps == nc.mLinkUpBandwidthKbps
+ && this.mLinkDownBandwidthKbps == nc.mLinkDownBandwidthKbps);
}
/** @hide */
public static int minBandwidth(int a, int b) {
@@ -1715,9 +1715,9 @@
*/
public boolean equalRequestableCapabilities(@Nullable NetworkCapabilities nc) {
if (nc == null) return false;
- return (equalsNetCapabilitiesRequestable(nc) &&
- equalsTransportTypes(nc) &&
- equalsSpecifier(nc));
+ return (equalsNetCapabilitiesRequestable(nc)
+ && equalsTransportTypes(nc)
+ && equalsSpecifier(nc));
}
@Override
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 8bfbad6..cad0db2 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -32,8 +32,8 @@
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.os.Build;
+import android.os.Process;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.telephony.SubscriptionPlan;
import android.util.DebugUtils;
import android.util.Pair;
@@ -160,7 +160,7 @@
/** @hide */
public static final int FOREGROUND_THRESHOLD_STATE =
- ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+ ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
/**
* {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
@@ -500,7 +500,7 @@
@Deprecated
public static boolean isUidValidForPolicy(Context context, int uid) {
// first, quick-reject non-applications
- if (!UserHandle.isApp(uid)) {
+ if (!Process.isApplicationUid(uid)) {
return false;
}
diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java
index 85bf79a..326943a 100644
--- a/core/java/android/net/PacProxySelector.java
+++ b/core/java/android/net/PacProxySelector.java
@@ -20,6 +20,7 @@
import android.util.Log;
import com.android.net.IProxyService;
+
import com.google.android.collect.Lists;
import java.io.IOException;
@@ -50,7 +51,7 @@
ServiceManager.getService(PROXY_SERVICE));
if (mProxyService == null) {
// Added because of b10267814 where mako is restarting.
- Log.e(TAG, "PacManager: no proxy service");
+ Log.e(TAG, "PacProxyInstaller: no proxy service");
}
mDefaultList = Lists.newArrayList(java.net.Proxy.NO_PROXY);
}
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index de5a180..950d393 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -127,7 +127,7 @@
}
/**
- * Only used in PacManager after Local Proxy is bound.
+ * Only used in PacProxyInstaller after Local Proxy is bound.
* @hide
*/
public ProxyInfo(@NonNull Uri pacFileUrl, int localProxyPort) {
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index 58ea915..bb91f89 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -137,7 +137,7 @@
* @return true if the event was successfully logged.
*/
public boolean log(@NonNull Network network, @NonNull int[] transports, @NonNull Event data) {
- return log(network.netId, transports, data);
+ return log(network.getNetId(), transports, data);
}
/**
diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/core/java/android/net/util/MultinetworkPolicyTracker.java
index aa0f622..8dfd4e1 100644
--- a/core/java/android/net/util/MultinetworkPolicyTracker.java
+++ b/core/java/android/net/util/MultinetworkPolicyTracker.java
@@ -34,7 +34,7 @@
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.util.Slog;
+import android.util.Log;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -204,13 +204,13 @@
@Override
public void onChange(boolean selfChange) {
- Slog.wtf(TAG, "Should never be reached.");
+ Log.wtf(TAG, "Should never be reached.");
}
@Override
public void onChange(boolean selfChange, Uri uri) {
if (!mSettingsUris.contains(uri)) {
- Slog.wtf(TAG, "Unexpected settings observation: " + uri);
+ Log.wtf(TAG, "Unexpected settings observation: " + uri);
}
reevaluate();
}
diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java
new file mode 100644
index 0000000..4d8cf91
--- /dev/null
+++ b/core/java/android/net/vcn/VcnTransportInfo.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.TransportInfo;
+import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.SubscriptionManager;
+
+import java.util.Objects;
+
+/**
+ * VcnTransportInfo contains information about the VCN's underlying transports for SysUi.
+ *
+ * <p>Presence of this class in the NetworkCapabilities.TransportInfo implies that the network is a
+ * VCN.
+ *
+ * <p>VcnTransportInfo must exist on top of either an underlying Wifi or Cellular Network. If the
+ * underlying Network is WiFi, the subId will be {@link
+ * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo
+ * will be {@code null}.
+ *
+ * @hide
+ */
+public class VcnTransportInfo implements TransportInfo, Parcelable {
+ @Nullable private final WifiInfo mWifiInfo;
+ private final int mSubId;
+
+ public VcnTransportInfo(@NonNull WifiInfo wifiInfo) {
+ this(wifiInfo, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+
+ public VcnTransportInfo(int subId) {
+ this(null /* wifiInfo */, subId);
+ }
+
+ private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId) {
+ if (wifiInfo == null && subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ throw new IllegalArgumentException(
+ "VcnTransportInfo requires either non-null WifiInfo or valid subId");
+ }
+
+ mWifiInfo = wifiInfo;
+ mSubId = subId;
+ }
+
+ /**
+ * Get the {@link WifiInfo} for this VcnTransportInfo.
+ *
+ * <p>If the underlying Network for the associated VCN is Cellular, returns null.
+ *
+ * @return the WifiInfo if there is an underlying WiFi connection, else null.
+ */
+ @Nullable
+ public WifiInfo getWifiInfo() {
+ return mWifiInfo;
+ }
+
+ /**
+ * Get the subId for the VCN Network associated with this VcnTransportInfo.
+ *
+ * <p>If the underlying Network for the associated VCN is WiFi, returns {@link
+ * SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
+ *
+ * @return the Subscription ID if a cellular underlying Network is present, else {@link
+ * android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID}.
+ */
+ public int getSubId() {
+ return mSubId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mWifiInfo, mSubId);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof VcnTransportInfo)) return false;
+ final VcnTransportInfo that = (VcnTransportInfo) o;
+
+ return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {}
+
+ /** Implement the Parcelable interface */
+ public static final @NonNull Creator<VcnTransportInfo> CREATOR =
+ new Creator<VcnTransportInfo>() {
+ public VcnTransportInfo createFromParcel(Parcel in) {
+ // return null instead of a default VcnTransportInfo to avoid leaking
+ // information about this being a VCN Network (instead of macro cellular, etc)
+ return null;
+ }
+
+ public VcnTransportInfo[] newArray(int size) {
+ return new VcnTransportInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 46ad7b8..305c686 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -22,11 +22,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.ActivityManager;
import android.content.Context;
-import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
@@ -41,12 +41,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
-/**
- * Class that provides a privileged API to capture and consume bugreports.
- *
- * @hide
- */
-@SystemApi
+/** Class that provides a privileged API to capture and consume bugreports. */
@SystemService(Context.BUGREPORT_SERVICE)
public final class BugreportManager {
@@ -61,28 +56,30 @@
mBinder = binder;
}
- /**
- * An interface describing the callback for bugreport progress and status.
- */
+ /** An interface describing the callback for bugreport progress and status. */
public abstract static class BugreportCallback {
- /** @hide */
+ /**
+ * Possible error codes taking a bugreport can encounter.
+ *
+ * @hide
+ */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = { "BUGREPORT_ERROR_" }, value = {
- BUGREPORT_ERROR_INVALID_INPUT,
- BUGREPORT_ERROR_RUNTIME,
- BUGREPORT_ERROR_USER_DENIED_CONSENT,
- BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
- BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
- })
-
- /** Possible error codes taking a bugreport can encounter */
+ @IntDef(
+ prefix = {"BUGREPORT_ERROR_"},
+ value = {
+ BUGREPORT_ERROR_INVALID_INPUT,
+ BUGREPORT_ERROR_RUNTIME,
+ BUGREPORT_ERROR_USER_DENIED_CONSENT,
+ BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
+ BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
+ })
public @interface BugreportErrorCode {}
/** The input options were invalid */
public static final int BUGREPORT_ERROR_INVALID_INPUT =
IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT;
- /** A runtime error occured */
+ /** A runtime error occurred */
public static final int BUGREPORT_ERROR_RUNTIME =
IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR;
@@ -100,6 +97,7 @@
/**
* Called when there is a progress update.
+ *
* @param progress the progress in [0.0, 100.0]
*/
public void onProgress(@FloatRange(from = 0f, to = 100f) float progress) {}
@@ -114,14 +112,12 @@
* out, but the bugreport could be available in the internal directory of dumpstate for
* manual retrieval.
*
- * <p> If {@code BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS} is passed, then the
- * caller should try later, as only one bugreport can be in progress at a time.
+ * <p>If {@code BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS} is passed, then the caller
+ * should try later, as only one bugreport can be in progress at a time.
*/
public void onError(@BugreportErrorCode int errorCode) {}
- /**
- * Called when taking bugreport finishes successfully.
- */
+ /** Called when taking bugreport finishes successfully. */
public void onFinished() {}
/**
@@ -138,20 +134,23 @@
* seconds to return in the worst case. {@code callback} will receive progress and status
* updates.
*
- * <p>The bugreport artifacts will be copied over to the given file descriptors only if the
- * user consents to sharing with the calling app.
+ * <p>The bugreport artifacts will be copied over to the given file descriptors only if the user
+ * consents to sharing with the calling app.
*
* <p>{@link BugreportManager} takes ownership of {@code bugreportFd} and {@code screenshotFd}.
*
- * @param bugreportFd file to write the bugreport. This should be opened in write-only,
- * append mode.
- * @param screenshotFd file to write the screenshot, if necessary. This should be opened
- * in write-only, append mode.
+ * @param bugreportFd file to write the bugreport. This should be opened in write-only, append
+ * mode.
+ * @param screenshotFd file to write the screenshot, if necessary. This should be opened in
+ * write-only, append mode.
* @param params options that specify what kind of a bugreport should be taken
* @param callback callback for progress and status updates
+ * @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.DUMP)
- public void startBugreport(@NonNull ParcelFileDescriptor bugreportFd,
+ public void startBugreport(
+ @NonNull ParcelFileDescriptor bugreportFd,
@Nullable ParcelFileDescriptor screenshotFd,
@NonNull BugreportParams params,
@NonNull @CallbackExecutor Executor executor,
@@ -165,17 +164,21 @@
boolean isScreenshotRequested = screenshotFd != null;
if (screenshotFd == null) {
// Binder needs a valid File Descriptor to be passed
- screenshotFd = ParcelFileDescriptor.open(new File("/dev/null"),
- ParcelFileDescriptor.MODE_READ_ONLY);
+ screenshotFd =
+ ParcelFileDescriptor.open(
+ new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
}
- DumpstateListener dsListener = new DumpstateListener(executor, callback,
- isScreenshotRequested);
+ DumpstateListener dsListener =
+ new DumpstateListener(executor, callback, isScreenshotRequested);
// Note: mBinder can get callingUid from the binder transaction.
- mBinder.startBugreport(-1 /* callingUid */,
+ mBinder.startBugreport(
+ -1 /* callingUid */,
mContext.getOpPackageName(),
bugreportFd.getFileDescriptor(),
screenshotFd.getFileDescriptor(),
- params.getMode(), dsListener, isScreenshotRequested);
+ params.getMode(),
+ dsListener,
+ isScreenshotRequested);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (FileNotFoundException e) {
@@ -189,13 +192,64 @@
}
}
- /*
- * Cancels a currently running bugreport.
+ /**
+ * Starts a connectivity bugreport.
+ *
+ * <p>The connectivity bugreport is a specialized version of bugreport that only includes
+ * information specifically for debugging connectivity-related issues (e.g. telephony, wi-fi,
+ * and IP networking issues). It is intended primarily for use by OEMs and network providers
+ * such as mobile network operators. In addition to generally excluding information that isn't
+ * targeted to connectivity debugging, this type of bugreport excludes PII and sensitive
+ * information that isn't strictly necessary for connectivity debugging.
+ *
+ * <p>The calling app MUST have a context-specific reason for requesting a connectivity
+ * bugreport, such as detecting a connectivity-related issue. This API SHALL NOT be used to
+ * perform random sampling from a fleet of public end-user devices.
+ *
+ * <p>Calling this API will cause the system to ask the user for consent every single time. The
+ * bugreport artifacts will be copied over to the given file descriptors only if the user
+ * consents to sharing with the calling app.
+ *
+ * <p>This starts a bugreport in the background. However the call itself can take several
+ * seconds to return in the worst case. {@code callback} will receive progress and status
+ * updates.
+ *
+ * <p>Requires that the calling app has carrier privileges (see {@link
+ * android.telephony.TelephonyManager#hasCarrierPrivileges}) on any active subscription.
+ *
+ * @param bugreportFd file to write the bugreport. This should be opened in write-only, append
+ * mode.
+ * @param callback callback for progress and status updates.
*/
- @RequiresPermission(android.Manifest.permission.DUMP)
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ public void startConnectivityBugreport(
+ @NonNull ParcelFileDescriptor bugreportFd,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull BugreportCallback callback) {
+ startBugreport(
+ bugreportFd,
+ null /* screenshotFd */,
+ new BugreportParams(BugreportParams.BUGREPORT_MODE_TELEPHONY),
+ executor,
+ callback);
+ }
+
+ /**
+ * Cancels the currently running bugreport.
+ *
+ * <p>Apps are only able to cancel their own bugreports. App A cannot cancel a bugreport started
+ * by app B.
+ *
+ * <p>Requires permission: {@link android.Manifest.permission#DUMP} or that the calling app has
+ * carrier privileges (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on
+ * any active subscription.
+ *
+ * @throws SecurityException if trying to cancel another app's bugreport in progress
+ */
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
public void cancelBugreport() {
try {
- mBinder.cancelBugreport();
+ mBinder.cancelBugreport(-1 /* callingUid */, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -205,23 +259,26 @@
* Requests a bugreport.
*
* <p>This requests the platform/system to take a bugreport and makes the final bugreport
- * available to the user. The user may choose to share it with another app, but the bugreport
- * is never given back directly to the app that requested it.
+ * available to the user. The user may choose to share it with another app, but the bugreport is
+ * never given back directly to the app that requested it.
*
- * @param params {@link BugreportParams} that specify what kind of a bugreport should
- * be taken, please note that not all kinds of bugreport allow for a
- * progress notification
- * @param shareTitle title on the final share notification
+ * @param params {@link BugreportParams} that specify what kind of a bugreport should be taken,
+ * please note that not all kinds of bugreport allow for a progress notification
+ * @param shareTitle title on the final share notification
* @param shareDescription description on the final share notification
+ * @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.DUMP)
- public void requestBugreport(@NonNull BugreportParams params, @Nullable CharSequence shareTitle,
+ public void requestBugreport(
+ @NonNull BugreportParams params,
+ @Nullable CharSequence shareTitle,
@Nullable CharSequence shareDescription) {
try {
String title = shareTitle == null ? null : shareTitle.toString();
String description = shareDescription == null ? null : shareDescription.toString();
- ActivityManager.getService().requestBugReportWithDescription(title, description,
- params.getMode());
+ ActivityManager.getService()
+ .requestBugReportWithDescription(title, description, params.getMode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -232,8 +289,8 @@
private final BugreportCallback mCallback;
private final boolean mIsScreenshotRequested;
- DumpstateListener(Executor executor, BugreportCallback callback,
- boolean isScreenshotRequested) {
+ DumpstateListener(
+ Executor executor, BugreportCallback callback, boolean isScreenshotRequested) {
mExecutor = executor;
mCallback = callback;
mIsScreenshotRequested = isScreenshotRequested;
@@ -243,9 +300,7 @@
public void onProgress(int progress) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> {
- mCallback.onProgress(progress);
- });
+ mExecutor.execute(() -> mCallback.onProgress(progress));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -255,9 +310,7 @@
public void onError(int errorCode) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> {
- mCallback.onError(errorCode);
- });
+ mExecutor.execute(() -> mCallback.onError(errorCode));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -267,9 +320,7 @@
public void onFinished() throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> {
- mCallback.onFinished();
- });
+ mExecutor.execute(() -> mCallback.onFinished());
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -284,20 +335,19 @@
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
mainThreadHandler.post(
() -> {
- int message = success ? R.string.bugreport_screenshot_success_toast
- : R.string.bugreport_screenshot_failure_toast;
+ int message =
+ success
+ ? R.string.bugreport_screenshot_success_toast
+ : R.string.bugreport_screenshot_failure_toast;
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
});
}
@Override
- public void onUiIntensiveBugreportDumpsFinished()
- throws RemoteException {
+ public void onUiIntensiveBugreportDumpsFinished() throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> {
- mCallback.onEarlyReportFinished();
- });
+ mExecutor.execute(() -> mCallback.onEarlyReportFinished());
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/os/PatternMatcher.java b/core/java/android/os/PatternMatcher.java
index 428405b..631c98a 100644
--- a/core/java/android/os/PatternMatcher.java
+++ b/core/java/android/os/PatternMatcher.java
@@ -61,6 +61,12 @@
*/
public static final int PATTERN_ADVANCED_GLOB = 3;
+ /**
+ * Pattern type: the given pattern must match the
+ * end of the string it is tested against.
+ */
+ public static final int PATTERN_SUFFIX = 4;
+
// token types for advanced matching
private static final int TOKEN_TYPE_LITERAL = 0;
private static final int TOKEN_TYPE_ANY = 1;
@@ -128,6 +134,9 @@
case PATTERN_ADVANCED_GLOB:
type = "ADVANCED: ";
break;
+ case PATTERN_SUFFIX:
+ type = "SUFFIX: ";
+ break;
}
return "PatternMatcher{" + type + mPattern + "}";
}
@@ -179,6 +188,8 @@
return matchGlobPattern(pattern, match);
} else if (type == PATTERN_ADVANCED_GLOB) {
return matchAdvancedPattern(parsedPattern, match);
+ } else if (type == PATTERN_SUFFIX) {
+ return match.endsWith(pattern);
}
return false;
}
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 086180e..b13be9f 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -2194,6 +2194,33 @@
onVmPolicyViolation(new IncorrectContextUseViolation(message, originStack));
}
+ /**
+ * A helper method to verify if the {@code context} is a UI context and throw
+ * {@link IncorrectContextUseViolation} if the {@code context} is not a UI context.
+ *
+ * @param context The context to verify if it is a UI context
+ * @param methodName The asserted method name
+ *
+ * @see Context#isUiContext()
+ * @see IncorrectContextUseViolation
+ *
+ * @hide
+ */
+ public static void assertUiContext(@NonNull Context context, @NonNull String methodName) {
+ if (vmIncorrectContextUseEnabled() && !context.isUiContext()) {
+ final String errorMessage = "Tried to access UI related API" + methodName
+ + " from a non-UI Context:" + context;
+ final String message = "UI-related services, such as WindowManager, WallpaperService "
+ + "or LayoutInflater should be accessed from Activity or other UI "
+ + "Contexts. Use an Activity or a Context created with "
+ + "Context#createWindowContext(int, Bundle), which are adjusted to "
+ + "the configuration and visual bounds of an area on screen.";
+ final Exception exception = new IllegalAccessException(errorMessage);
+ StrictMode.onIncorrectContextUsed(message, exception);
+ Log.e(TAG, errorMessage + " " + message, exception);
+ }
+ }
+
/** Assume locked until we hear otherwise */
private static volatile boolean sUserKeyUnlocked = false;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index e7d19c5..ed60baf 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2040,13 +2040,16 @@
}
/**
- * Checks if specified user can have restricted profile.
+ * Checks if the calling context user can have a restricted profile.
+ * @return whether the context user can have a restricted profile.
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
- public boolean canHaveRestrictedProfile(@UserIdInt int userId) {
+ @UserHandleAware
+ public boolean canHaveRestrictedProfile() {
try {
- return mService.canHaveRestrictedProfile(userId);
+ return mService.canHaveRestrictedProfile(mUserId);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2068,6 +2071,25 @@
}
/**
+ * Get the parent of a restricted profile.
+ *
+ * @return the parent of the user or {@code null} if the user is not restricted profile
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS})
+ @UserHandleAware
+ public @Nullable UserHandle getRestrictedProfileParent() {
+ final UserInfo info = getUserInfo(mUserId);
+ if (info == null) return null;
+ if (!info.isRestricted()) return null;
+ final int parent = info.restrictedProfileParentId;
+ if (parent == UserHandle.USER_NULL) return null;
+ return UserHandle.of(parent);
+ }
+
+ /**
* Checks if a user is a guest user.
* @return whether user is a guest user.
* @hide
diff --git a/core/java/android/permission/PermGroupUsage.java b/core/java/android/permission/PermGroupUsage.java
index 7335e00..c94c0ff 100644
--- a/core/java/android/permission/PermGroupUsage.java
+++ b/core/java/android/permission/PermGroupUsage.java
@@ -79,7 +79,7 @@
@Override
public String toString() {
return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this))
- + "packageName: " + mPackageName + ", UID: " + mUid + ", permGroup: "
- + mPermGroupName + ", isActive: " + mIsActive + ",attribution: " + mAttribution;
+ + " packageName: " + mPackageName + ", UID: " + mUid + ", permGroup: "
+ + mPermGroupName + ", isActive: " + mIsActive + ", attribution: " + mAttribution;
}
}
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index 00ba867..c28b59b 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -31,14 +31,26 @@
import android.annotation.NonNull;
import android.app.AppOpsManager;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.Attribution;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.icu.text.ListFormatter;
import android.location.LocationManager;
import android.os.Process;
import android.os.UserHandle;
import android.provider.DeviceConfig;
+import android.provider.Settings;
+import android.speech.RecognitionService;
+import android.speech.RecognizerIntent;
import android.util.ArrayMap;
-import android.util.Pair;
+import android.util.ArraySet;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
import java.util.ArrayList;
import java.util.Collections;
@@ -69,6 +81,9 @@
/** How long after an access to show it as "running" */
private static final String RUNNING_ACCESS_TIME_MS = "running_acccess_time_ms";
+ /** The name of the expected voice IME subtype */
+ private static final String VOICE_IME_SUBTYPE = "voice";
+
private static final long DEFAULT_RUNNING_TIME_MS = 5000L;
private static final long DEFAULT_RECENT_TIME_MS = 30000L;
@@ -168,13 +183,25 @@
}
Map<String, List<OpUsage>> rawUsages = getOpUsages(ops);
+ Set<List<PackageAttribution>> proxyChains = getProxyChains(rawUsages.get(MICROPHONE));
Map<PackageAttribution, CharSequence> packagesWithAttributionLabels =
- getTrustedAttributions(rawUsages.get(MICROPHONE));
+ getTrustedAttributions(rawUsages.get(MICROPHONE), proxyChains);
List<String> usedPermGroups = new ArrayList<>(rawUsages.keySet());
for (int permGroupNum = 0; permGroupNum < usedPermGroups.size(); permGroupNum++) {
boolean isPhone = false;
String permGroup = usedPermGroups.get(permGroupNum);
+
+ Map<PackageAttribution, CharSequence> pkgAttrLabels = packagesWithAttributionLabels;
+ Set<List<PackageAttribution>> proxies = proxyChains;
+ if (!MICROPHONE.equals(permGroup)) {
+ pkgAttrLabels = new ArrayMap<>();
+ proxies = new ArraySet<>();
+ }
+
+ List<OpUsage> permUsages = removeDuplicatesAndProxies(rawUsages.get(permGroup),
+ pkgAttrLabels.keySet(), proxies);
+
if (permGroup.equals(OPSTR_PHONE_CALL_MICROPHONE)) {
isPhone = true;
permGroup = MICROPHONE;
@@ -183,9 +210,8 @@
permGroup = CAMERA;
}
- int numUsages = rawUsages.get(permGroup).size();
- for (int usageNum = 0; usageNum < numUsages; usageNum++) {
- OpUsage usage = rawUsages.get(permGroup).get(usageNum);
+ for (int usageNum = 0; usageNum < permUsages.size(); usageNum++) {
+ OpUsage usage = permUsages.get(usageNum);
usages.add(new PermGroupUsage(usage.packageName, usage.uid, permGroup,
usage.lastAccessTime, usage.isRunning, isPhone,
packagesWithAttributionLabels.get(usage.toPackageAttr())));
@@ -256,7 +282,7 @@
AppOpsManager.OpEventProxyInfo proxy = attrOpEntry.getLastProxyInfo(opFlags);
if (proxy != null && proxy.getPackageName() != null) {
proxyUsage = new OpUsage(proxy.getPackageName(), proxy.getAttributionTag(),
- uid, lastAccessTime, isRunning, null);
+ proxy.getUid(), lastAccessTime, isRunning, null);
}
String permGroupName = getGroupForOp(op);
@@ -291,77 +317,374 @@
return flattenedUsages;
}
- // TODO ntmyren: create JavaDoc and copy merging of proxy chains and trusted labels from
- // "usages" livedata in ReviewOngoingUsageLiveData
- private Map<PackageAttribution, CharSequence> getTrustedAttributions(List<OpUsage> usages) {
+ /**
+ * Take the list of all usages, figure out any proxy chains, get all possible special
+ * attribution labels, and figure out which usages need to show a special label, if any.
+ *
+ * @param usages The raw permission usages
+ *
+ * @return A map of package + attribution (in the form of a PackageAttribution object) to
+ * trusted attribution label, if there is one
+ */
+ private ArrayMap<PackageAttribution, CharSequence> getTrustedAttributions(
+ List<OpUsage> usages, Set<List<PackageAttribution>> proxyChains) {
ArrayMap<PackageAttribution, CharSequence> attributions = new ArrayMap<>();
if (usages == null) {
return attributions;
}
- Set<List<OpUsage>> proxyChains = getProxyChains(usages);
- Map<Pair<String, UserHandle>, CharSequence> trustedLabels = getTrustedAttributionLabels();
+ Map<PackageAttribution, CharSequence> trustedLabels =
+ getTrustedAttributionLabels(usages);
+
+ for (List<PackageAttribution> chain : proxyChains) {
+ // If this chain is empty, or has only one link, then do not show any special labels
+ if (chain.size() <= 1) {
+ continue;
+ }
+
+ // If the last link in the chain is not user sensitive, do not show it.
+ boolean lastLinkIsUserSensitive = false;
+ for (int i = 0; i < usages.size(); i++) {
+ PackageAttribution lastLink = chain.get(chain.size() - 1);
+ if (lastLink.equals(usages.get(i).toPackageAttr())) {
+ lastLinkIsUserSensitive = true;
+ break;
+ }
+ }
+ if (!lastLinkIsUserSensitive) {
+ continue;
+ }
+
+ List<CharSequence> labels = new ArrayList<>();
+ for (int i = 0; i < chain.size(); i++) {
+ // If this is the last link in the proxy chain, assign it the series of labels
+ // Else, if it has a special label, add that label
+ // Else, if there are no other apps in the remaining part of the chain which
+ // have the same package name, add the app label
+ // If it is not the last link in the chain, remove its attribution
+ PackageAttribution attr = chain.get(i);
+ CharSequence trustedLabel = trustedLabels.get(attr);
+ if (i == chain.size() - 1) {
+ attributions.put(attr, formatLabelList(labels));
+ } else if (trustedLabel != null && !labels.contains(trustedLabel)) {
+ labels.add(trustedLabel);
+ trustedLabels.remove(attr);
+ } else {
+ boolean remainingChainHasPackage = false;
+ for (int attrNum = i + 1; attrNum < chain.size() - 1; attrNum++) {
+ if (chain.get(i).packageName.equals(attr.packageName)) {
+ remainingChainHasPackage = true;
+ break;
+ }
+ }
+ if (!remainingChainHasPackage) {
+ try {
+ ApplicationInfo appInfo = mPkgManager.getApplicationInfoAsUser(
+ attr.packageName, 0, attr.getUser());
+ CharSequence appLabel = appInfo.loadLabel(
+ getUserContext(attr.getUser()).getPackageManager());
+ labels.add(appLabel);
+ } catch (PackageManager.NameNotFoundException e) {
+ // Do nothing
+ }
+ }
+ }
+ }
+ }
+
+ for (PackageAttribution attr : trustedLabels.keySet()) {
+ attributions.put(attr, trustedLabels.get(attr));
+ }
return attributions;
}
- // TODO ntmyren: create JavaDoc and copy proxyChainsLiveData from ReviewOngoingUsageLiveData
- private Set<List<OpUsage>> getProxyChains(List<OpUsage> usages) {
- Map<PackageAttribution, List<OpUsage>> inProgressChains = new ArrayMap<>();
- List<OpUsage> remainingUsages = new ArrayList<>(usages);
- // find all one-link chains (that is, all proxied apps whose proxy is not included in
- // the usage list)
- for (int usageNum = 0; usageNum < usages.size(); usageNum++) {
- OpUsage usage = usages.get(usageNum);
- PackageAttribution usageAttr = usage.toPackageAttr();
- if (usage.proxy == null) {
- continue;
- }
- PackageAttribution proxyAttr = usage.proxy.toPackageAttr();
- boolean proxyExists = false;
- for (int otherUsageNum = 0; otherUsageNum < usages.size(); otherUsageNum++) {
- if (usages.get(otherUsageNum).toPackageAttr().equals(proxyAttr)) {
- proxyExists = true;
- break;
- }
- }
-
- if (!proxyExists) {
- inProgressChains.put(usageAttr, List.of(usage));
- remainingUsages.remove(usage);
- }
- }
-
- // find all possible starting points for chains
- for (int i = 0; i < usages.size(); i++) {
- OpUsage usage = usages.get(i);
- }
-
- /*
- // find all possible starting points for chains
- for (usage in remainingProxyChainUsages.toList()) {
- // if this usage has no proxy, but proxies another usage, it is the start of a chain
- val usageAttr = getPackageAttr(usage)
- if (usage.proxyAccess == null && remainingProxyChainUsages.any {
- it.proxyAccess != null && getPackageAttr(it.proxyAccess) == usageAttr
- }) {
- inProgressChains[usageAttr] = mutableListOf(usage)
- }
-
- // if this usage is a chain start, or no usage have this usage as a proxy, remove it
- if (usage.proxyAccess == null) {
- remainingProxyChainUsages.remove(usage)
- }
- }
-
- */
-
- return null;
+ private CharSequence formatLabelList(List<CharSequence> labels) {
+ return ListFormatter.getInstance().format(labels);
}
- // TODO ntmyren: create JavaDoc and copy trustedAttrsLiveData from ReviewOngoingUsageLiveData
- private Map<Pair<String, UserHandle>, CharSequence> getTrustedAttributionLabels() {
- return new ArrayMap<>();
+ /**
+ * Get all chains of proxy usages. A proxy chain is defined as one usage at the root, then
+ * further proxy usages, where the app and attribution tag of the proxy in the proxy usage
+ * matches the previous usage in the chain.
+ *
+ * @param usages The permission usages
+ *
+ * @return A set of lists of package attributions. One list represents a chain of proxy usages,
+ * with the start of the chain (the usage without a proxy) at position 0, and each usage down
+ * the chain has the previous one listed as a proxy usage.
+ */
+ private Set<List<PackageAttribution>> getProxyChains(List<OpUsage> usages) {
+ if (usages == null) {
+ return new ArraySet<>();
+ }
+
+ ArrayMap<PackageAttribution, ArrayList<PackageAttribution>> proxyChains = new ArrayMap<>();
+ // map of usages that still need to be removed, or added to a chain
+ ArrayMap<PackageAttribution, OpUsage> remainingUsages = new ArrayMap<>();
+ // map of usage.proxy -> usage, telling us if a usage is a proxy
+ ArrayMap<PackageAttribution, PackageAttribution> proxies = new ArrayMap<>();
+ for (int i = 0; i < usages.size(); i++) {
+ OpUsage usage = usages.get(i);
+ remainingUsages.put(usage.toPackageAttr(), usage);
+ if (usage.proxy != null) {
+ proxies.put(usage.proxy.toPackageAttr(), usage.toPackageAttr());
+ }
+ }
+
+ // find all possible end points for chains
+ List<PackageAttribution> keys = new ArrayList<>(remainingUsages.keySet());
+ for (int usageNum = 0; usageNum < remainingUsages.size(); usageNum++) {
+ OpUsage usage = remainingUsages.get(keys.get(usageNum));
+ if (usage == null) {
+ continue;
+ }
+ PackageAttribution usageAttr = usage.toPackageAttr();
+ // If this usage has a proxy, but is not a proxy, it is the end of a chain.
+ // If it has no proxy, and isn't a proxy, remove it.
+ if (!proxies.containsKey(usageAttr) && usage.proxy != null) {
+ ArrayList<PackageAttribution> proxyList = new ArrayList<>();
+ proxyList.add(usageAttr);
+ proxyChains.put(usageAttr, proxyList);
+ } else if (!proxies.containsKey(usageAttr) && usage.proxy == null) {
+ remainingUsages.remove(keys.get(usageNum));
+ }
+ }
+
+ // assemble the chains in reverse order, then invert them
+ for (int numStart = 0; numStart < proxyChains.size(); numStart++) {
+ PackageAttribution currPackageAttr = proxyChains.keyAt(numStart);
+ ArrayList<PackageAttribution> proxyChain = proxyChains.get(currPackageAttr);
+ OpUsage currentUsage = remainingUsages.get(currPackageAttr);
+ if (currentUsage == null || proxyChain == null) {
+ continue;
+ }
+ while (currentUsage.proxy != null) {
+ currPackageAttr = currentUsage.proxy.toPackageAttr();
+ currentUsage = remainingUsages.get(currPackageAttr);
+
+ boolean invalidState = false;
+ for (int chainNum = 0; chainNum < proxyChain.size(); chainNum++) {
+ if (currentUsage == null || proxyChain.get(chainNum).equals(currPackageAttr)) {
+ // either our current value is not in the usage list, or we have a cycle
+ invalidState = true;
+ break;
+ }
+ }
+
+ if (invalidState) {
+ break;
+ }
+
+ proxyChain.add(currPackageAttr);
+ }
+ // invert the lists, so the element without a proxy is first on the list
+ Collections.reverse(proxyChain);
+ }
+
+ return new ArraySet<>(proxyChains.values());
+ }
+
+ /**
+ * Gets all trusted proxied voice IME and voice recognition microphone uses, and get the
+ * label needed to display with it, as well as information about the proxy whose label is being
+ * shown, if applicable.
+ *
+ * @param usages The permission usages
+ *
+ * @return A map of package attribution -> the attribution label for that package attribution,
+ * if applicable
+ */
+ private Map<PackageAttribution, CharSequence> getTrustedAttributionLabels(
+ List<OpUsage> usages) {
+ List<UserHandle> users = new ArrayList<>();
+ for (int i = 0; i < usages.size(); i++) {
+ UserHandle user = UserHandle.getUserHandleForUid(usages.get(i).uid);
+ if (!users.contains(user)) {
+ users.add(user);
+ }
+ }
+
+ Map<PackageAttribution, CharSequence> trustedLabels = new ArrayMap<>();
+ for (int userNum = 0; userNum < users.size(); userNum++) {
+ UserHandle user = users.get(userNum);
+ Context userContext = mContext.createContextAsUser(user, 0);
+
+ // Get all voice IME labels
+ Map<String, CharSequence> voiceInputs = new ArrayMap<>();
+ List<InputMethodInfo> inputs = userContext.getSystemService(InputMethodManager.class)
+ .getEnabledInputMethodList();
+ for (int inputNum = 0; inputNum < inputs.size(); inputNum++) {
+ InputMethodInfo input = inputs.get(inputNum);
+ for (int subtypeNum = 0; subtypeNum < input.getSubtypeCount(); subtypeNum++) {
+ if (VOICE_IME_SUBTYPE.equals(input.getSubtypeAt(subtypeNum).getMode())) {
+ voiceInputs.put(input.getPackageName(), input.getServiceInfo()
+ .loadUnsafeLabel(userContext.getPackageManager()));
+ break;
+ }
+ }
+ }
+
+ // Get the currently selected recognizer from the secure setting
+ String recognitionPackageName = Settings.Secure.getString(
+ userContext.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
+ if (recognitionPackageName == null) {
+ continue;
+ }
+ recognitionPackageName =
+ ComponentName.unflattenFromString(recognitionPackageName).getPackageName();
+ Map<String, CharSequence> recognizers = new ArrayMap<>();
+ List<ResolveInfo> availableRecognizers = mPkgManager.queryIntentServicesAsUser(
+ new Intent(RecognitionService.SERVICE_INTERFACE), PackageManager.GET_META_DATA,
+ user.getIdentifier());
+ for (int recogNum = 0; recogNum < availableRecognizers.size(); recogNum++) {
+ ResolveInfo info = availableRecognizers.get(recogNum);
+ if (recognitionPackageName.equals(info.serviceInfo.packageName)) {
+ recognizers.put(recognitionPackageName, info.serviceInfo.loadUnsafeLabel(
+ userContext.getPackageManager()));
+ }
+ }
+
+ Map<String, CharSequence> recognizerIntents = new ArrayMap<>();
+ List<ResolveInfo> availableRecognizerIntents = mPkgManager.queryIntentActivitiesAsUser(
+ new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH),
+ PackageManager.GET_META_DATA, user);
+ for (int recogNum = 0; recogNum < availableRecognizerIntents.size(); recogNum++) {
+ ResolveInfo info = availableRecognizerIntents.get(recogNum);
+ if (info.activityInfo == null) {
+ continue;
+ }
+ String pkgName = info.activityInfo.packageName;
+ if (recognitionPackageName.equals(pkgName) && recognizers.containsKey(pkgName)) {
+ recognizerIntents.put(pkgName, recognizers.get(pkgName));
+ }
+ }
+ for (int usageNum = 0; usageNum < usages.size(); usageNum++) {
+ setTrustedAttrsForAccess(usages.get(usageNum), user, false, voiceInputs,
+ trustedLabels);
+ setTrustedAttrsForAccess(usages.get(usageNum), user, false, recognizerIntents,
+ trustedLabels);
+ setTrustedAttrsForAccess(usages.get(usageNum), user, true, recognizers,
+ trustedLabels);
+ }
+ }
+
+ return trustedLabels;
+ }
+
+ private void setTrustedAttrsForAccess(OpUsage opUsage, UserHandle currUser, boolean getProxy,
+ Map<String, CharSequence> trustedMap, Map<PackageAttribution, CharSequence> toSetMap) {
+ OpUsage usage = opUsage;
+ if (getProxy) {
+ usage = opUsage.proxy;
+ }
+
+ if (usage == null || !usage.getUser().equals(currUser)
+ || !trustedMap.containsKey(usage.packageName)) {
+ return;
+ }
+
+ CharSequence label = getAttributionLabel(usage);
+ if (trustedMap.get(usage.packageName).equals(label)) {
+ toSetMap.put(opUsage.toPackageAttr(), label);
+ }
+ }
+
+ private CharSequence getAttributionLabel(OpUsage usage) {
+ if (usage.attributionTag == null) {
+ return null;
+ }
+
+ PackageInfo pkgInfo;
+ try {
+ pkgInfo = mPkgManager.getPackageInfoAsUser(usage.packageName,
+ PackageManager.GET_ATTRIBUTIONS, usage.getUser().getIdentifier());
+ if (pkgInfo.attributions == null || pkgInfo.attributions.length == 0) {
+ return null;
+ }
+ for (int attrNum = 0; attrNum < pkgInfo.attributions.length; attrNum++) {
+ Attribution attr = pkgInfo.attributions[attrNum];
+ if (usage.attributionTag.equals(attr.getTag())) {
+ return mContext.createPackageContextAsUser(usage.packageName, 0,
+ usage.getUser()).getString(attr.getLabel());
+ }
+ }
+ return null;
+ } catch (PackageManager.NameNotFoundException e) {
+ return null;
+ }
+ }
+
+ /**
+ * If we have multiple usages of a
+ * @param rawUsages The list of all usages that we wish to
+ * @param specialAttributions A set of all usages that have a special label
+ * @param proxies A list of proxy chains- all links but the last on the chain should be removed,
+ * if the last link has a special label
+ * @return A list of usages without duplicates or proxy usages.
+ */
+ private List<OpUsage> removeDuplicatesAndProxies(List<OpUsage> rawUsages,
+ Set<PackageAttribution> specialAttributions,
+ Set<List<PackageAttribution>> proxies) {
+ List<OpUsage> deDuped = new ArrayList<>();
+ if (rawUsages == null) {
+ return deDuped;
+ }
+
+ List<PackageAttribution> toRemoveProxies = new ArrayList<>();
+ for (List<PackageAttribution> proxyList: proxies) {
+ PackageAttribution lastLink = proxyList.get(proxyList.size() - 1);
+ if (!specialAttributions.contains(lastLink)) {
+ continue;
+ }
+ for (int proxyNum = 0; proxyNum < proxyList.size(); proxyNum++) {
+ if (!proxyList.get(proxyNum).equals(lastLink)) {
+ toRemoveProxies.add(proxyList.get(proxyNum));
+ }
+ }
+ }
+
+ for (int usageNum = 0; usageNum < rawUsages.size(); usageNum++) {
+ OpUsage usage = rawUsages.get(usageNum);
+
+ // If this attribution has a special attribution, do not remove it
+ if (specialAttributions.contains(usage.toPackageAttr())) {
+ deDuped.add(usage);
+ }
+
+ // If this attribution is a proxy, remove it
+ if (toRemoveProxies.contains(usage.toPackageAttr())) {
+ continue;
+ }
+
+
+ // Search the rest of the list for usages with the same UID. If this is the most recent
+ // usage for that uid, keep it. Otherwise, remove it
+ boolean isMostRecentForUid = true;
+ for (int otherUsageNum = 0; otherUsageNum < rawUsages.size(); otherUsageNum++) {
+ OpUsage otherUsage = rawUsages.get(otherUsageNum);
+ if (otherUsage.uid == usage.uid) {
+ if (otherUsage.isRunning && !usage.isRunning) {
+ isMostRecentForUid = false;
+ } else if (usage.isRunning
+ && otherUsage.lastAccessTime >= usage.lastAccessTime) {
+ isMostRecentForUid = false;
+ } else if (otherUsage.lastAccessTime >= usage.lastAccessTime) {
+ isMostRecentForUid = false;
+ }
+
+ if (!isMostRecentForUid) {
+ break;
+ }
+ }
+ }
+
+ if (isMostRecentForUid) {
+ deDuped.add(usage);
+ }
+ }
+
+ return deDuped;
}
private boolean isUserSensitive(String packageName, UserHandle user, String op) {
@@ -407,6 +730,10 @@
public PackageAttribution toPackageAttr() {
return new PackageAttribution(packageName, attributionTag, uid);
}
+
+ public UserHandle getUser() {
+ return UserHandle.getUserHandleForUid(uid);
+ }
}
/**
@@ -438,5 +765,9 @@
public int hashCode() {
return Objects.hash(packageName, attributionTag, uid);
}
+
+ public UserHandle getUser() {
+ return UserHandle.getUserHandleForUid(uid);
+ }
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 9db7ca0..27ba72b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1018,6 +1018,20 @@
"android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
/**
+ * Activity Action: Show settings to manage all SIM profiles.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MANAGE_ALL_SUBSCRIPTIONS_SETTINGS =
+ "android.settings.MANAGE_ALL_SUBSCRIPTIONS_SETTINGS";
+
+ /**
* Activity Action: Show screen for controlling which apps can draw on top of other apps.
* <p>
* In some cases, a matching Activity may not exist, so ensure you safeguard against this.
@@ -8440,14 +8454,6 @@
"emergency_gesture_sound_enabled";
/**
- * The default number to call in emergency gesture
- *
- * @hide
- */
- public static final String EMERGENCY_GESTURE_CALL_NUMBER =
- "emergency_gesture_call_number";
-
- /**
* Whether the camera launch gesture to double tap the power button when the screen is off
* should be disabled.
*
diff --git a/core/java/android/service/search/OWNERS b/core/java/android/service/search/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/core/java/android/service/search/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index a5ca9ef..b229212 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -40,7 +40,6 @@
public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX;
public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
- public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
public static final String SETTINGS_WIFITRACKER2 = "settings_wifitracker2";
/** @hide */
public static final String SETTINGS_DO_NOT_RESTORE_PRESERVED =
@@ -54,7 +53,6 @@
DEFAULT_FLAGS = new HashMap<>();
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
- DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 388096e..c2566cc 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -207,7 +207,7 @@
Index.FRAME_COMPLETED,
})
@Retention(RetentionPolicy.SOURCE)
- private @interface Index {
+ public @interface Index {
int FLAGS = 0;
int FRAME_TIMELINE_VSYNC_ID = 1;
int INTENDED_VSYNC = 2;
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 2d26c64..b4e1172 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -642,7 +642,7 @@
updateState(state);
applyLocalVisibilityOverride();
- if (!mState.equals(lastState, true /* excludingCaptionInsets */,
+ if (!mState.equals(lastState, false /* excludingCaptionInsets */,
true /* excludeInvisibleIme */)) {
if (DEBUG) Log.d(TAG, "onStateChanged, notifyInsetsChanged");
mHost.notifyInsetsChanged();
@@ -672,16 +672,14 @@
getSourceConsumer(type).updateSource(source, animationType);
}
for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
+ // Only update the server side insets here.
+ if (type == ITYPE_CAPTION_BAR) continue;
InsetsSource source = mState.peekSource(type);
if (source == null) continue;
if (newState.peekSource(type) == null) {
mState.removeSource(type);
}
}
- if (mCaptionInsetsHeight != 0) {
- mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
- mFrame.right, mFrame.top + mCaptionInsetsHeight));
- }
updateDisabledUserAnimationTypes(disabledUserAnimationTypes);
@@ -1488,7 +1486,16 @@
@Override
public void setCaptionInsetsHeight(int height) {
- mCaptionInsetsHeight = height;
+ if (mCaptionInsetsHeight != height) {
+ mCaptionInsetsHeight = height;
+ if (mCaptionInsetsHeight != 0) {
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
+ mFrame.right, mFrame.top + mCaptionInsetsHeight));
+ } else {
+ mState.removeSource(ITYPE_CAPTION_BAR);
+ }
+ mHost.notifyInsetsChanged();
+ }
}
@Override
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index ac5d14e..258a72c 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -270,7 +270,7 @@
pw.print(" clipRect="); clipRect.printShortString(pw);
pw.print(" contentInsets="); contentInsets.printShortString(pw);
pw.print(" prefixOrderIndex="); pw.print(prefixOrderIndex);
- pw.print(" position="); position.dump(pw);
+ pw.print(" position="); printPoint(position, pw);
pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw);
pw.print(" screenSpaceBounds="); screenSpaceBounds.printShortString(pw);
pw.print(" localBounds="); localBounds.printShortString(pw);
@@ -303,6 +303,10 @@
proto.end(token);
}
+ private static void printPoint(Point p, PrintWriter pw) {
+ pw.print("["); pw.print(p.x); pw.print(","); pw.print(p.y); pw.print("]");
+ }
+
public static final @android.annotation.NonNull Creator<RemoteAnimationTarget> CREATOR
= new Creator<RemoteAnimationTarget>() {
public RemoteAnimationTarget createFromParcel(Parcel in) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 2f97357..63ee927 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -266,12 +266,12 @@
/** @hide */
@IntDef(flag = true, value = {JANK_NONE,
- JANK_DISPLAY,
+ DISPLAY_HAL,
JANK_SURFACEFLINGER_DEADLINE_MISSED,
JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED,
JANK_APP_DEADLINE_MISSED,
- JANK_PREDICTION_EXPIRED,
- JANK_SURFACEFLINGER_EARLY_LATCH})
+ PREDICTION_ERROR,
+ SURFACE_FLINGER_SCHEDULING})
@Retention(RetentionPolicy.SOURCE)
public @interface JankType {}
@@ -281,7 +281,7 @@
public static final int JANK_NONE = 0x0;
// Jank not related to SurfaceFlinger or the App
- public static final int JANK_DISPLAY = 0x1;
+ public static final int DISPLAY_HAL = 0x1;
// SF took too long on the CPU
public static final int JANK_SURFACEFLINGER_DEADLINE_MISSED = 0x2;
// SF took too long on the GPU
@@ -291,9 +291,16 @@
// Predictions live for 120ms, if prediction is expired for a frame, there is definitely a
// jank
// associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame.
- public static final int JANK_PREDICTION_EXPIRED = 0x10;
+ public static final int PREDICTION_ERROR = 0x10;
// Latching a buffer early might cause an early present of the frame
- public static final int JANK_SURFACEFLINGER_EARLY_LATCH = 0x20;
+ public static final int SURFACE_FLINGER_SCHEDULING = 0x20;
+ // A buffer is said to be stuffed if it was expected to be presented on a vsync but was
+ // presented later because the previous buffer was presented in its expected vsync. This
+ // usually happens if there is an unexpectedly long frame causing the rest of the buffers
+ // to enter a stuffed state.
+ public static final int BUFFER_STUFFING = 0x40;
+ // Jank due to unknown reasons.
+ public static final int UNKNOWN = 0x80;
public JankData(long frameVsyncId, @JankType int jankType) {
this.frameVsyncId = frameVsyncId;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e8584da..25967b3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10448,7 +10448,7 @@
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
protected boolean isVisibleToUser(Rect boundInView) {
if (mAttachInfo != null) {
// Attached to invisible window means this view is not visible.
@@ -17914,6 +17914,7 @@
* @see #setOutlineProvider(ViewOutlineProvider)
* @see #getClipToOutline()
*/
+ @RemotableViewMethod
public void setClipToOutline(boolean clipToOutline) {
damageInParent();
if (getClipToOutline() != clipToOutline) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0097b2e..7e0ebbc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1787,18 +1787,18 @@
/** Register callbacks to be notified when the ViewRootImpl surface changes. */
- interface SurfaceChangedCallback {
+ public interface SurfaceChangedCallback {
void surfaceCreated(Transaction t);
void surfaceReplaced(Transaction t);
void surfaceDestroyed();
}
private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>();
- void addSurfaceChangedCallback(SurfaceChangedCallback c) {
+ public void addSurfaceChangedCallback(SurfaceChangedCallback c) {
mSurfaceChangedCallbacks.add(c);
}
- void removeSurfaceChangedCallback(SurfaceChangedCallback c) {
+ public void removeSurfaceChangedCallback(SurfaceChangedCallback c) {
mSurfaceChangedCallbacks.remove(c);
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 482f2f0..45fa41b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -663,24 +663,34 @@
}
/**
- * Message for taking fullscreen screenshot
+ * Invoke screenshot flow to capture a full-screen image.
* @hide
*/
int TAKE_SCREENSHOT_FULLSCREEN = 1;
/**
- * Message for taking screenshot of selected region.
+ * Invoke screenshot flow allowing the user to select a region.
* @hide
*/
int TAKE_SCREENSHOT_SELECTED_REGION = 2;
/**
- * Message for handling a screenshot flow with an image provided by the caller.
+ * Invoke screenshot flow with an image provided by the caller.
* @hide
*/
int TAKE_SCREENSHOT_PROVIDED_IMAGE = 3;
/**
+ * Enum listing the types of screenshot requests available.
+ *
+ * @hide
+ */
+ @IntDef({TAKE_SCREENSHOT_FULLSCREEN,
+ TAKE_SCREENSHOT_SELECTED_REGION,
+ TAKE_SCREENSHOT_PROVIDED_IMAGE})
+ @interface ScreenshotType {}
+
+ /**
* Enum listing the possible sources from which a screenshot was originated. Used for logging.
*
* @hide
@@ -1518,7 +1528,54 @@
* can use {@link #FLAG_ALT_FOCUSABLE_IM} to modify this behavior. */
public static final int FLAG_NOT_FOCUSABLE = 0x00000008;
- /** Window flag: this window can never receive touch events. */
+ /**
+ * Window flag: this window can never receive touch events.
+ *
+ * <p>The intention of this flag is to leave the touch to be handled by some window below
+ * this window (in Z order).
+ *
+ * <p>Starting from Android {@link Build.VERSION_CODES#S}, for security reasons, touch
+ * events that pass through windows containing this flag (ie. are within the bounds of the
+ * window) will only be delivered to the touch-consuming window if one (or more) of the
+ * items below are true:
+ * <ol>
+ * <li><b>Same UID</b>: This window belongs to the same UID that owns the touch-consuming
+ * window.
+ * <li><b>Trusted windows</b>: This window is trusted. Trusted windows include (but are
+ * not limited to) accessibility windows ({@link #TYPE_ACCESSIBILITY_OVERLAY}), the IME
+ * ({@link #TYPE_INPUT_METHOD}) and assistant windows (TYPE_VOICE_INTERACTION). Windows of
+ * type {@link #TYPE_APPLICATION_OVERLAY} are <b>not</b> trusted, see below.
+ * <li><b>Invisible windows</b>: This window is {@link View#GONE} or
+ * {@link View#INVISIBLE}.
+ * <li><b>Fully transparent windows</b>: This window has {@link LayoutParams#alpha} equal
+ * to 0.
+ * <li><b>One SAW window with enough transparency</b>: This window is of type {@link
+ * #TYPE_APPLICATION_OVERLAY}, has {@link LayoutParams#alpha} below or equal to <b>0.8</b>
+ * and it's the <b>only</b> window of type {@link #TYPE_APPLICATION_OVERLAY} from this UID
+ * in the touch path.
+ * <li><b>Multiple SAW windows with enough transparency</b>: The multiple overlapping
+ * {@link #TYPE_APPLICATION_OVERLAY} windows in the
+ * touch path from this UID have a <b>combined obscuring opacity</b> below or equal to
+ * <b>0.8</b>. See section below on how to compute this value.
+ * </ol>
+ * <p>If none of these cases hold, the touch will not be delivered and a message will be
+ * logged to logcat.</p>
+ *
+ * <a name="ObscuringOpacity"></a>
+ * <h3>Combined obscuring opacity</h3>
+ *
+ * <p>The <b>combined obscuring opacity</b> of a set of windows is obtained by combining the
+ * opacity values of all windows in the set using the associative and commutative operation
+ * defined as:
+ * <pre>
+ * opacity({A,B}) = 1 - (1 - opacity(A))*(1 - opacity(B))
+ * </pre>
+ * <p>where {@code opacity(X)} is the {@link LayoutParams#alpha} of window X. So, for a set
+ * of windows {@code {W1, .., Wn}}, the combined obscuring opacity will be:
+ * <pre>
+ * opacity({W1, .., Wn}) = 1 - (1 - opacity(W1)) * ... * (1 - opacity(Wn))
+ * </pre>
+ */
public static final int FLAG_NOT_TOUCHABLE = 0x00000010;
/** Window flag: even when this window is focusable (its
@@ -2084,6 +2141,16 @@
*/
public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004;
+ /**
+ * When set {@link LayoutParams#TYPE_APPLICATION_OVERLAY} windows will stay visible, even if
+ * {@link LayoutParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} is set for another
+ * visible window.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(permission.SYSTEM_APPLICATION_OVERLAY)
+ public static final int SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY = 0x00000008;
+
/** In a multiuser system if this flag is set and the owner is a system process then this
* window will appear on all user screens. This overrides the default behavior of window
* types that normally only appear on the owning user's screen. Refer to each window type
@@ -2281,6 +2348,7 @@
@IntDef(flag = true, prefix = { "SYSTEM_FLAG_" }, value = {
SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
SYSTEM_FLAG_SHOW_FOR_ALL_USERS,
+ SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY,
})
public @interface SystemFlags {}
@@ -2314,6 +2382,7 @@
PRIVATE_FLAG_TRUSTED_OVERLAY,
PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME,
PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP,
+ SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY,
})
public @interface PrivateFlags {}
@@ -2426,7 +2495,11 @@
@ViewDebug.FlagToString(
mask = PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP,
equals = PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP,
- name = "INTERCEPT_GLOBAL_DRAG_AND_DROP")
+ name = "INTERCEPT_GLOBAL_DRAG_AND_DROP"),
+ @ViewDebug.FlagToString(
+ mask = SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY,
+ equals = SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY,
+ name = "SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY")
})
@PrivateFlags
@TestApi
diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS
index ac80d9f..4bcdeea 100644
--- a/core/java/android/view/textclassifier/OWNERS
+++ b/core/java/android/view/textclassifier/OWNERS
@@ -6,3 +6,5 @@
svetoslavganov@google.com
augale@google.com
joannechung@google.com
+tonymak@google.com
+licha@google.com
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 5b32649..c1913f6 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -137,6 +137,15 @@
return mExtras;
}
+ /** @hide */
+ public TextSelection.Builder toBuilder() {
+ return new TextSelection.Builder(mStartIndex, mEndIndex)
+ .setId(mId)
+ .setEntityConfidence(mEntityConfidence)
+ .setTextClassification(mTextClassification)
+ .setExtras(mExtras);
+ }
+
@Override
public String toString() {
return String.format(
@@ -188,6 +197,12 @@
return this;
}
+ Builder setEntityConfidence(EntityConfidence scores) {
+ mEntityConfidence.clear();
+ mEntityConfidence.putAll(scores.toMap());
+ return this;
+ }
+
/**
* Sets an id for the TextSelection object.
*/
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index e4de400..ed20d26 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -196,11 +196,6 @@
initImageView();
- // ImageView is not important by default, unless app developer overrode attribute.
- if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
- setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
- }
-
final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
saveAttributeDataForStyleable(context, R.styleable.ImageView,
@@ -265,6 +260,15 @@
sCompatDrawableVisibilityDispatch = targetSdkVersion < Build.VERSION_CODES.N;
sCompatDone = true;
}
+
+ // By default, ImageView is not important for autofill but important for content capture.
+ // Developers can override these defaults via the corresponding attributes.
+ if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
+ setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_NO);
+ }
+ if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+ setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
+ }
}
@Override
diff --git a/core/java/android/window/IRemoteTransition.aidl b/core/java/android/window/IRemoteTransition.aidl
new file mode 100644
index 0000000..e0ddf05
--- /dev/null
+++ b/core/java/android/window/IRemoteTransition.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+
+/**
+ * Interface allowing remote processes to play transition animations.
+ * The usage flow is as follows:
+ * <p><ol>
+ * <li>The remote tags a lifecycle event with an IRemoteTransition (via a parameter in
+ * ActivityOptions#makeRemoteAnimation) or a transition matches a filter registered via
+ * Transitions#registerRemote.
+ * <li>Shell then associates the transition for the event with the IRemoteTransition
+ * <li>Shell receives onTransitionReady and delegates the animation to the IRemoteTransition
+ * via {@link #startAnimation}.
+ * <li>Once the IRemoteTransition is done animating, it will call the finishCallback.
+ * <li>Shell/Core finish-up the transition.
+ * </ul>
+ *
+ * {@hide}
+ */
+oneway interface IRemoteTransition {
+ /**
+ * Starts a transition animation. Once complete, the implementation should call
+ * `finishCallback`.
+ */
+ void startAnimation(in TransitionInfo info, in SurfaceControl.Transaction t,
+ in IRemoteAnimationFinishedCallback finishCallback);
+}
diff --git a/core/java/android/window/ITransitionPlayer.aidl b/core/java/android/window/ITransitionPlayer.aidl
index 55d47cb..af37fbc 100644
--- a/core/java/android/window/ITransitionPlayer.aidl
+++ b/core/java/android/window/ITransitionPlayer.aidl
@@ -16,10 +16,9 @@
package android.window;
-import android.app.ActivityManager;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
-import android.window.WindowContainerTransaction;
+import android.window.TransitionRequestInfo;
/**
* Implemented by WMShell to initiate and play transition animations.
@@ -56,12 +55,9 @@
* Called when something in WMCore requires a transition to play -- for example when an Activity
* is started in a new Task.
*
- * @param type The {@link WindowManager#TransitionType} of the transition to start.
* @param transitionToken An identifying token for the transition that needs to be started.
* Pass this to {@link IWindowOrganizerController#startTransition}.
- * @param triggerTask If non-null, the task containing the activity whose lifecycle change
- * (start or finish) has caused this transition to occur.
+ * @param request Information about this particular request.
*/
- void requestStartTransition(int type, in IBinder transitionToken,
- in ActivityManager.RunningTaskInfo triggerTask);
+ void requestStartTransition(in IBinder transitionToken, in TransitionRequestInfo request);
}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl b/core/java/android/window/TransitionFilter.aidl
similarity index 74%
copy from media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
copy to core/java/android/window/TransitionFilter.aidl
index 0e6fcde..19c76d1 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
+++ b/core/java/android/window/TransitionFilter.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,11 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.window;
-/**
- * Information required to request a Tuner Lnb.
- *
- * @hide
- */
-parcelable TunerLnbRequest;
\ No newline at end of file
+parcelable TransitionFilter;
diff --git a/core/java/android/window/TransitionFilter.java b/core/java/android/window/TransitionFilter.java
new file mode 100644
index 0000000..4421f06
--- /dev/null
+++ b/core/java/android/window/TransitionFilter.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.WindowConfiguration;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A parcelable filter that can be used for rerouting transitions to a remote. This is a local
+ * representation so that the transition system doesn't need to make blocking queries over
+ * binder.
+ *
+ * @hide
+ */
+public final class TransitionFilter implements Parcelable {
+
+ /**
+ * When non-null: this is a list of transition types that this filter applies to. This filter
+ * will fail for transitions that aren't one of these types.
+ */
+ @Nullable public int[] mTypeSet = null;
+
+ /**
+ * A list of required changes. To pass, a transition must meet all requirements.
+ */
+ @Nullable public Requirement[] mRequirements = null;
+
+ public TransitionFilter() {
+ }
+
+ private TransitionFilter(Parcel in) {
+ mTypeSet = in.createIntArray();
+ mRequirements = in.createTypedArray(Requirement.CREATOR);
+ }
+
+ /** @return true if `info` meets all the requirements to pass this filter. */
+ public boolean matches(@NonNull TransitionInfo info) {
+ if (mTypeSet != null) {
+ // non-null typeset, so make sure info is one of the types.
+ boolean typePass = false;
+ for (int i = 0; i < mTypeSet.length; ++i) {
+ if (info.getType() == mTypeSet[i]) {
+ typePass = true;
+ break;
+ }
+ }
+ if (!typePass) return false;
+ }
+ // Make sure info meets all of the requirements.
+ if (mRequirements != null) {
+ for (int i = 0; i < mRequirements.length; ++i) {
+ if (!mRequirements[i].matches(info)) return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ /** @hide */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeIntArray(mTypeSet);
+ dest.writeTypedArray(mRequirements, flags);
+ }
+
+ @NonNull
+ public static final Creator<TransitionFilter> CREATOR =
+ new Creator<TransitionFilter>() {
+ @Override
+ public TransitionFilter createFromParcel(Parcel in) {
+ return new TransitionFilter(in);
+ }
+
+ @Override
+ public TransitionFilter[] newArray(int size) {
+ return new TransitionFilter[size];
+ }
+ };
+
+ @Override
+ /** @hide */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{types=[");
+ if (mTypeSet != null) {
+ for (int i = 0; i < mTypeSet.length; ++i) {
+ sb.append((i == 0 ? "" : ",") + mTypeSet[i]);
+ }
+ }
+ sb.append("] checks=[");
+ if (mRequirements != null) {
+ for (int i = 0; i < mRequirements.length; ++i) {
+ sb.append((i == 0 ? "" : ",") + mRequirements[i]);
+ }
+ }
+ return sb.append("]}").toString();
+ }
+
+ /**
+ * Matches a change that a transition must contain to pass this filter. All requirements in a
+ * filter must be met to pass the filter.
+ */
+ public static final class Requirement implements Parcelable {
+ public int mActivityType = ACTIVITY_TYPE_UNDEFINED;
+ public int[] mModes = null;
+
+ public Requirement() {
+ }
+
+ private Requirement(Parcel in) {
+ mActivityType = in.readInt();
+ mModes = in.createIntArray();
+ }
+
+ /** Go through changes and find if at-least one change matches this filter */
+ boolean matches(@NonNull TransitionInfo info) {
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ if (change.getParent() != null) {
+ // Only look at the top animating windows.
+ continue;
+ }
+ if (mActivityType != ACTIVITY_TYPE_UNDEFINED) {
+ if (change.getTaskInfo() == null
+ || change.getTaskInfo().getActivityType() != mActivityType) {
+ continue;
+ }
+ }
+ if (mModes != null) {
+ boolean pass = false;
+ for (int m = 0; m < mModes.length; ++m) {
+ if (mModes[m] == change.getMode()) {
+ pass = true;
+ break;
+ }
+ }
+ if (!pass) continue;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /** Check if the request matches this filter. It may generate false positives */
+ boolean matches(@NonNull TransitionRequestInfo request) {
+ // Can't check modes since the transition hasn't been built at this point.
+ if (mActivityType == ACTIVITY_TYPE_UNDEFINED) return true;
+ return request.getTriggerTask() != null
+ && request.getTriggerTask().getActivityType() == mActivityType;
+ }
+
+ @Override
+ /** @hide */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mActivityType);
+ dest.writeIntArray(mModes);
+ }
+
+ @NonNull
+ public static final Creator<Requirement> CREATOR =
+ new Creator<Requirement>() {
+ @Override
+ public Requirement createFromParcel(Parcel in) {
+ return new Requirement(in);
+ }
+
+ @Override
+ public Requirement[] newArray(int size) {
+ return new Requirement[size];
+ }
+ };
+
+ @Override
+ /** @hide */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder out = new StringBuilder();
+ out.append("{atype=" + WindowConfiguration.activityTypeToString(mActivityType));
+ out.append(" modes=[");
+ if (mModes != null) {
+ for (int i = 0; i < mModes.length; ++i) {
+ out.append((i == 0 ? "" : ",") + TransitionInfo.modeToString(mModes[i]));
+ }
+ }
+ return out.append("]}").toString();
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl b/core/java/android/window/TransitionRequestInfo.aidl
similarity index 74%
copy from media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
copy to core/java/android/window/TransitionRequestInfo.aidl
index 0e6fcde..d2b9ccf 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
+++ b/core/java/android/window/TransitionRequestInfo.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,11 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.window;
-/**
- * Information required to request a Tuner Lnb.
- *
- * @hide
- */
-parcelable TunerLnbRequest;
\ No newline at end of file
+parcelable TransitionRequestInfo;
diff --git a/core/java/android/window/TransitionRequestInfo.java b/core/java/android/window/TransitionRequestInfo.java
new file mode 100644
index 0000000..cc493ab
--- /dev/null
+++ b/core/java/android/window/TransitionRequestInfo.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.os.Parcelable;
+import android.view.WindowManager;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Used to communicate information about what is changing during a transition to a TransitionPlayer.
+ * @hide
+ */
+@DataClass(genToString = true, genSetters = true, genAidl = true)
+public final class TransitionRequestInfo implements Parcelable {
+
+ /** The type of the transition being requested. */
+ private final @WindowManager.TransitionType int mType;
+
+ /**
+ * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * finish) has caused this transition to occur.
+ */
+ private @Nullable ActivityManager.RunningTaskInfo mTriggerTask;
+
+ /** If non-null, a remote-transition associated with the source of this transition. */
+ private @Nullable IRemoteTransition mRemoteTransition;
+
+
+
+ // Code below generated by codegen v1.0.22.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/window/TransitionRequestInfo.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new TransitionRequestInfo.
+ *
+ * @param type
+ * The type of the transition being requested.
+ * @param triggerTask
+ * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * finish) has caused this transition to occur.
+ * @param remoteTransition
+ * If non-null, a remote-transition associated with the source of this transition.
+ */
+ @DataClass.Generated.Member
+ public TransitionRequestInfo(
+ @WindowManager.TransitionType int type,
+ @Nullable ActivityManager.RunningTaskInfo triggerTask,
+ @Nullable IRemoteTransition remoteTransition) {
+ this.mType = type;
+ com.android.internal.util.AnnotationValidations.validate(
+ WindowManager.TransitionType.class, null, mType);
+ this.mTriggerTask = triggerTask;
+ this.mRemoteTransition = remoteTransition;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The type of the transition being requested.
+ */
+ @DataClass.Generated.Member
+ public @WindowManager.TransitionType int getType() {
+ return mType;
+ }
+
+ /**
+ * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * finish) has caused this transition to occur.
+ */
+ @DataClass.Generated.Member
+ public @Nullable ActivityManager.RunningTaskInfo getTriggerTask() {
+ return mTriggerTask;
+ }
+
+ /**
+ * If non-null, a remote-transition associated with the source of this transition.
+ */
+ @DataClass.Generated.Member
+ public @Nullable IRemoteTransition getRemoteTransition() {
+ return mRemoteTransition;
+ }
+
+ /**
+ * If non-null, If non-null, the task containing the activity whose lifecycle change (start or
+ * finish) has caused this transition to occur.
+ */
+ @DataClass.Generated.Member
+ public @android.annotation.NonNull TransitionRequestInfo setTriggerTask(@android.annotation.NonNull ActivityManager.RunningTaskInfo value) {
+ mTriggerTask = value;
+ return this;
+ }
+
+ /**
+ * If non-null, a remote-transition associated with the source of this transition.
+ */
+ @DataClass.Generated.Member
+ public @android.annotation.NonNull TransitionRequestInfo setRemoteTransition(@android.annotation.NonNull IRemoteTransition value) {
+ mRemoteTransition = value;
+ return this;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "TransitionRequestInfo { " +
+ "type = " + mType + ", " +
+ "triggerTask = " + mTriggerTask + ", " +
+ "remoteTransition = " + mRemoteTransition +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@android.annotation.NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mTriggerTask != null) flg |= 0x2;
+ if (mRemoteTransition != null) flg |= 0x4;
+ dest.writeByte(flg);
+ dest.writeInt(mType);
+ if (mTriggerTask != null) dest.writeTypedObject(mTriggerTask, flags);
+ if (mRemoteTransition != null) dest.writeStrongInterface(mRemoteTransition);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ TransitionRequestInfo(@android.annotation.NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int type = in.readInt();
+ ActivityManager.RunningTaskInfo triggerTask = (flg & 0x2) == 0 ? null : (ActivityManager.RunningTaskInfo) in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+ IRemoteTransition remoteTransition = (flg & 0x4) == 0 ? null : IRemoteTransition.Stub.asInterface(in.readStrongBinder());
+
+ this.mType = type;
+ com.android.internal.util.AnnotationValidations.validate(
+ WindowManager.TransitionType.class, null, mType);
+ this.mTriggerTask = triggerTask;
+ this.mRemoteTransition = remoteTransition;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @android.annotation.NonNull Parcelable.Creator<TransitionRequestInfo> CREATOR
+ = new Parcelable.Creator<TransitionRequestInfo>() {
+ @Override
+ public TransitionRequestInfo[] newArray(int size) {
+ return new TransitionRequestInfo[size];
+ }
+
+ @Override
+ public TransitionRequestInfo createFromParcel(@android.annotation.NonNull android.os.Parcel in) {
+ return new TransitionRequestInfo(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1610060387917L,
+ codegenVersion = "1.0.22",
+ sourceFile = "frameworks/base/core/java/android/window/TransitionRequestInfo.java",
+ inputSignatures = "private final @android.view.WindowManager.TransitionType int mType\nprivate @android.annotation.Nullable android.app.ActivityManager.RunningTaskInfo mTriggerTask\nprivate @android.annotation.Nullable android.window.IRemoteTransition mRemoteTransition\nclass TransitionRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 34e03af..c235c82 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -218,6 +218,7 @@
public static final int SELECTION_TYPE_STANDARD = 3;
public static final int SELECTION_TYPE_COPY = 4;
public static final int SELECTION_TYPE_NEARBY = 5;
+ public static final int SELECTION_TYPE_EDIT = 6;
private static final int SCROLL_STATUS_IDLE = 0;
private static final int SCROLL_STATUS_SCROLLING_VERTICAL = 1;
@@ -1197,6 +1198,37 @@
}
@VisibleForTesting
+ protected @Nullable ComponentName getEditSharingComponent() {
+ String editorPackage = getApplicationContext().getString(R.string.config_systemImageEditor);
+ if (editorPackage == null || TextUtils.isEmpty(editorPackage)) {
+ return null;
+ }
+ return ComponentName.unflattenFromString(editorPackage);
+ }
+
+ @VisibleForTesting
+ protected TargetInfo getEditSharingTarget(Intent originalIntent) {
+ final ComponentName cn = getEditSharingComponent();
+
+ final Intent resolveIntent = new Intent(originalIntent);
+ resolveIntent.setComponent(cn);
+ resolveIntent.setAction(Intent.ACTION_EDIT);
+ final ResolveInfo ri = getPackageManager().resolveActivity(
+ resolveIntent, PackageManager.GET_META_DATA);
+ if (ri == null || ri.activityInfo == null) {
+ Log.e(TAG, "Device-specified image edit component (" + cn
+ + ") not available");
+ return null;
+ }
+
+ final DisplayResolveInfo dri = new DisplayResolveInfo(
+ originalIntent, ri, getString(R.string.screenshot_edit), "", resolveIntent, null);
+ dri.setDisplayIcon(getDrawable(R.drawable.ic_menu_edit));
+ return dri;
+ }
+
+
+ @VisibleForTesting
protected TargetInfo getNearbySharingTarget(Intent originalIntent) {
final ComponentName cn = getNearbySharingComponent();
if (cn == null) return null;
@@ -1282,6 +1314,27 @@
return b;
}
+ private @Nullable Button createEditButton(Intent originalIntent) {
+ final TargetInfo ti = getEditSharingTarget(originalIntent);
+ if (ti == null) return null;
+
+ final Button b = createActionButton(
+ ti.getDisplayIcon(this),
+ ti.getDisplayLabel(),
+ (View unused) -> {
+ // Log share completion via edit
+ getChooserActivityLogger().logShareTargetSelected(
+ SELECTION_TYPE_EDIT,
+ "",
+ -1);
+ safelyStartActivity(ti);
+ finish();
+ }
+ );
+ b.setId(R.id.chooser_edit_button);
+ return b;
+ }
+
private void addActionButton(ViewGroup parent, Button b) {
if (b == null) return;
final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(
@@ -1378,6 +1431,7 @@
(ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row);
//TODO: addActionButton(actionRow, createCopyButton());
addActionButton(actionRow, createNearbyButton(targetIntent));
+ addActionButton(actionRow, createEditButton(targetIntent));
mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false);
diff --git a/core/java/com/android/internal/app/ChooserActivityLogger.java b/core/java/com/android/internal/app/ChooserActivityLogger.java
index 426859e..c0cc483 100644
--- a/core/java/com/android/internal/app/ChooserActivityLogger.java
+++ b/core/java/com/android/internal/app/ChooserActivityLogger.java
@@ -118,7 +118,9 @@
@UiEvent(doc = "User selected the copy target.")
SHARESHEET_COPY_TARGET_SELECTED(235),
@UiEvent(doc = "User selected the nearby target.")
- SHARESHEET_NEARBY_TARGET_SELECTED(626);
+ SHARESHEET_NEARBY_TARGET_SELECTED(626),
+ @UiEvent(doc = "User selected the edit target.")
+ SHARESHEET_EDIT_TARGET_SELECTED(627);
private final int mId;
SharesheetTargetSelectedEvent(int id) {
@@ -140,6 +142,8 @@
return SHARESHEET_COPY_TARGET_SELECTED;
case ChooserActivity.SELECTION_TYPE_NEARBY:
return SHARESHEET_NEARBY_TARGET_SELECTED;
+ case ChooserActivity.SELECTION_TYPE_EDIT:
+ return SHARESHEET_EDIT_TARGET_SELECTED;
default:
return INVALID;
}
diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java
index 8986938..fc95275 100644
--- a/core/java/com/android/internal/infra/ServiceConnector.java
+++ b/core/java/com/android/internal/infra/ServiceConnector.java
@@ -24,6 +24,7 @@
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
@@ -40,6 +41,7 @@
import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Function;
@@ -220,11 +222,13 @@
private final @NonNull ServiceConnection mServiceConnection = this;
private final @NonNull Runnable mTimeoutDisconnect = this;
+ // This context contains the user information.
protected final @NonNull Context mContext;
private final @NonNull Intent mIntent;
private final int mBindingFlags;
- private final int mUserId;
private final @Nullable Function<IBinder, I> mBinderAsInterface;
+ private final @NonNull Handler mHandler;
+ private final @NonNull Executor mExecutor;
private volatile I mService = null;
private boolean mBinding = false;
@@ -249,11 +253,13 @@
*/
public Impl(@NonNull Context context, @NonNull Intent intent, int bindingFlags,
@UserIdInt int userId, @Nullable Function<IBinder, I> binderAsInterface) {
- mContext = context;
+ mContext = context.createContextAsUser(UserHandle.of(userId), 0);
mIntent = intent;
mBindingFlags = bindingFlags;
- mUserId = userId;
mBinderAsInterface = binderAsInterface;
+
+ mHandler = getJobHandler();
+ mExecutor = new HandlerExecutor(mHandler);
}
/**
@@ -292,14 +298,12 @@
* <p>
* If overridden, implementation must use at least the provided {@link ServiceConnection}
*/
- protected boolean bindService(
- @NonNull ServiceConnection serviceConnection, @NonNull Handler handler) {
+ protected boolean bindService(@NonNull ServiceConnection serviceConnection) {
if (DEBUG) {
logTrace();
}
- return mContext.bindServiceAsUser(mIntent, serviceConnection,
- Context.BIND_AUTO_CREATE | mBindingFlags,
- handler, UserHandle.of(mUserId));
+ return mContext.bindService(mIntent, Context.BIND_AUTO_CREATE | mBindingFlags,
+ mExecutor, serviceConnection);
}
/**
@@ -381,13 +385,13 @@
if (!enqueue((Job<I, ?>) task)) {
task.completeExceptionally(new IllegalStateException(
"Failed to post a job to handler. Likely "
- + getJobHandler().getLooper() + " is exiting"));
+ + mHandler.getLooper() + " is exiting"));
}
}
private boolean enqueue(@NonNull Job<I, ?> job) {
cancelTimeout();
- return getJobHandler().post(() -> enqueueJobThread(job));
+ return mHandler.post(() -> enqueueJobThread(job));
}
void enqueueJobThread(@NonNull Job<I, ?> job) {
@@ -404,7 +408,7 @@
} else if (isBound()) {
processQueue();
} else if (!mBinding) {
- if (bindService(mServiceConnection, getJobHandler())) {
+ if (bindService(mServiceConnection)) {
mBinding = true;
} else {
completeExceptionally(job,
@@ -497,7 +501,7 @@
logTrace();
}
mUnbinding = true;
- getJobHandler().post(this::unbindJobThread);
+ mHandler.post(this::unbindJobThread);
}
void unbindJobThread() {
@@ -606,7 +610,7 @@
public String toString() {
StringBuilder sb = new StringBuilder("ServiceConnector@")
.append(System.identityHashCode(this) % 1000).append("(")
- .append(mIntent).append(", user: ").append(mUserId)
+ .append(mIntent).append(", user: ").append(mContext.getUser().getIdentifier())
.append(")[").append(stateToString());
if (!mQueue.isEmpty()) {
sb.append(", ").append(mQueue.size()).append(" pending job(s)");
@@ -624,8 +628,8 @@
String tab = " ";
pw.append(prefix).append("ServiceConnector:").println();
pw.append(prefix).append(tab).append(String.valueOf(mIntent)).println();
- pw.append(prefix).append(tab)
- .append("userId: ").append(String.valueOf(mUserId)).println();
+ pw.append(prefix).append(tab).append("userId: ")
+ .append(String.valueOf(mContext.getUser().getIdentifier())).println();
pw.append(prefix).append(tab)
.append("State: ").append(stateToString()).println();
pw.append(prefix).append(tab)
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 36514ff..e82cc73 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -16,13 +16,28 @@
package com.android.internal.jank;
+import static android.view.SurfaceControl.JankData.BUFFER_STUFFING;
+import static android.view.SurfaceControl.JankData.DISPLAY_HAL;
+import static android.view.SurfaceControl.JankData.JANK_APP_DEADLINE_MISSED;
+import static android.view.SurfaceControl.JankData.JANK_NONE;
+import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_DEADLINE_MISSED;
+import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED;
+import static android.view.SurfaceControl.JankData.PREDICTION_ERROR;
+import static android.view.SurfaceControl.JankData.SURFACE_FLINGER_SCHEDULING;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.HardwareRendererObserver;
import android.os.Handler;
import android.os.Trace;
import android.util.Log;
+import android.util.SparseArray;
+import android.view.Choreographer;
import android.view.FrameMetrics;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.JankData.JankType;
import android.view.ThreadedRenderer;
+import android.view.ViewRootImpl;
import com.android.internal.jank.InteractionJankMonitor.Session;
import com.android.internal.util.FrameworkStatsLog;
@@ -31,68 +46,141 @@
* A class that allows the app to get the frame metrics from HardwareRendererObserver.
* @hide
*/
-public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
- private static final String TAG = FrameTracker.class.getSimpleName();
+public class FrameTracker extends SurfaceControl.OnJankDataListener
+ implements HardwareRendererObserver.OnFrameMetricsAvailableListener {
+ private static final String TAG = "FrameTracker";
private static final boolean DEBUG = false;
- //TODO (163431584): need also consider other refresh rates.
- private static final long JANK_THRESHOLD_NANOS = 1000000000 / 60;
- private static final long UNKNOWN_TIMESTAMP = -1;
+
+ private static final long INVALID_ID = -1;
public static final int NANOS_IN_MILLISECOND = 1_000_000;
private final HardwareRendererObserver mObserver;
+ private SurfaceControl mSurfaceControl;
private final int mTraceThresholdMissedFrames;
private final int mTraceThresholdFrameTimeMillis;
private final ThreadedRendererWrapper mRendererWrapper;
private final FrameMetricsWrapper mMetricsWrapper;
+ private final SparseArray<JankInfo> mJankInfos = new SparseArray<>();
+ private final Session mSession;
+ private final ViewRootWrapper mViewRoot;
+ private final SurfaceControlWrapper mSurfaceControlWrapper;
+ private final ViewRootImpl.SurfaceChangedCallback mSurfaceChangedCallback;
+ private final Handler mHandler;
+ private final ChoreographerWrapper mChoreographer;
- private long mBeginTime = UNKNOWN_TIMESTAMP;
- private long mEndTime = UNKNOWN_TIMESTAMP;
- private boolean mSessionEnd;
+ private long mBeginVsyncId = INVALID_ID;
+ private long mEndVsyncId = INVALID_ID;
+ private boolean mMetricsFinalized;
private boolean mCancelled = false;
- private int mTotalFramesCount = 0;
- private int mMissedFramesCount = 0;
- private int mSfMissedFramesCount = 0;
- private long mMaxFrameTimeNanos = 0;
- private Session mSession;
+ private static class JankInfo {
+ long frameVsyncId;
+ long totalDurationNanos;
+ boolean isFirstFrame;
+ boolean hwuiCallbackFired;
+ boolean surfaceControlCallbackFired;
+ @JankType int jankType;
+
+ static JankInfo createFromHwuiCallback(long frameVsyncId, long totalDurationNanos,
+ boolean isFirstFrame) {
+ return new JankInfo(frameVsyncId, true, false, JANK_NONE, totalDurationNanos,
+ isFirstFrame);
+ }
+
+ static JankInfo createFromSurfaceControlCallback(long frameVsyncId,
+ @JankType int jankType) {
+ return new JankInfo(frameVsyncId, false, true, jankType, 0, false /* isFirstFrame */);
+ }
+
+ private JankInfo(long frameVsyncId, boolean hwuiCallbackFired,
+ boolean surfaceControlCallbackFired, @JankType int jankType,
+ long totalDurationNanos, boolean isFirstFrame) {
+ this.frameVsyncId = frameVsyncId;
+ this.hwuiCallbackFired = hwuiCallbackFired;
+ this.surfaceControlCallbackFired = surfaceControlCallbackFired;
+ this.totalDurationNanos = totalDurationNanos;
+ this.jankType = jankType;
+ this.isFirstFrame = isFirstFrame;
+ }
+ }
public FrameTracker(@NonNull Session session, @NonNull Handler handler,
- @NonNull ThreadedRendererWrapper renderer, @NonNull FrameMetricsWrapper metrics,
- int traceThresholdMissedFrames, int traceThresholdFrameTimeMillis) {
+ @NonNull ThreadedRendererWrapper renderer, @NonNull ViewRootWrapper viewRootWrapper,
+ @NonNull SurfaceControlWrapper surfaceControlWrapper,
+ @NonNull ChoreographerWrapper choreographer,
+ @NonNull FrameMetricsWrapper metrics, int traceThresholdMissedFrames,
+ int traceThresholdFrameTimeMillis) {
mSession = session;
mRendererWrapper = renderer;
mMetricsWrapper = metrics;
+ mViewRoot = viewRootWrapper;
+ mChoreographer = choreographer;
+ mSurfaceControlWrapper = surfaceControlWrapper;
+ mHandler = handler;
mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
mTraceThresholdMissedFrames = traceThresholdMissedFrames;
mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis;
+
+ // If the surface isn't valid yet, wait until it's created.
+ if (viewRootWrapper.getSurfaceControl().isValid()) {
+ mSurfaceControl = viewRootWrapper.getSurfaceControl();
+ }
+ mSurfaceChangedCallback = new ViewRootImpl.SurfaceChangedCallback() {
+ @Override
+ public void surfaceCreated(SurfaceControl.Transaction t) {
+ synchronized (FrameTracker.this) {
+ if (mSurfaceControl == null) {
+ mSurfaceControl = viewRootWrapper.getSurfaceControl();
+ if (mBeginVsyncId != INVALID_ID) {
+ mSurfaceControlWrapper.addJankStatsListener(
+ FrameTracker.this, mSurfaceControl);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void surfaceReplaced(SurfaceControl.Transaction t) {
+ }
+
+ @Override
+ public void surfaceDestroyed() {
+
+ // Wait a while to give the system a chance for the remaining frames to arrive, then
+ // force finish the session.
+ mHandler.postDelayed(() -> {
+ synchronized (FrameTracker.this) {
+ if (!mMetricsFinalized) {
+ finish(mJankInfos.size() - 1);
+ }
+ }
+ }, 50);
+ }
+ };
+ viewRootWrapper.addSurfaceChangedCallback(mSurfaceChangedCallback);
}
/**
* Begin a trace session of the CUJ.
*/
public synchronized void begin() {
- long timestamp = System.nanoTime();
- if (DEBUG) {
- Log.d(TAG, "begin: time(ns)=" + timestamp + ", begin(ns)=" + mBeginTime
- + ", end(ns)=" + mEndTime + ", session=" + mSession.getName());
- }
- mBeginTime = timestamp;
- mEndTime = UNKNOWN_TIMESTAMP;
- Trace.beginAsyncSection(mSession.getName(), (int) mBeginTime);
+ mBeginVsyncId = mChoreographer.getVsyncId() + 1;
+ Trace.beginAsyncSection(mSession.getName(), (int) mBeginVsyncId);
mRendererWrapper.addObserver(mObserver);
+ if (mSurfaceControl != null) {
+ mSurfaceControlWrapper.addJankStatsListener(this, mSurfaceControl);
+ }
}
/**
* End the trace session of the CUJ.
*/
public synchronized void end() {
- long timestamp = System.nanoTime();
- if (DEBUG) {
- Log.d(TAG, "end: time(ns)=" + timestamp + ", begin(ns)=" + mBeginTime
- + ", end(ns)=" + mEndTime + ", session=" + mSession.getName());
+ mEndVsyncId = mChoreographer.getVsyncId();
+ Trace.endAsyncSection(mSession.getName(), (int) mBeginVsyncId);
+ if (mEndVsyncId == mBeginVsyncId) {
+ cancel();
}
- mEndTime = timestamp;
- Trace.endAsyncSection(mSession.getName(), (int) mBeginTime);
// We don't remove observer here,
// will remove it when all the frame metrics in this duration are called back.
// See onFrameMetricsAvailable for the logic of removing the observer.
@@ -102,14 +190,45 @@
* Cancel the trace session of the CUJ.
*/
public synchronized void cancel() {
- if (mBeginTime == UNKNOWN_TIMESTAMP || mEndTime != UNKNOWN_TIMESTAMP) return;
- if (DEBUG) {
- Log.d(TAG, "cancel: time(ns)=" + System.nanoTime() + ", begin(ns)=" + mBeginTime
- + ", end(ns)=" + mEndTime + ", session=" + mSession.getName());
- }
- Trace.endAsyncSection(mSession.getName(), (int) mBeginTime);
- mRendererWrapper.removeObserver(mObserver);
+ if (mBeginVsyncId == INVALID_ID || mEndVsyncId != INVALID_ID) return;
+ Trace.endAsyncSection(mSession.getName(), (int) mBeginVsyncId);
mCancelled = true;
+ removeObservers();
+ }
+
+ @Override
+ public synchronized void onJankDataAvailable(SurfaceControl.JankData[] jankData) {
+ if (mCancelled) {
+ return;
+ }
+
+ for (SurfaceControl.JankData jankStat : jankData) {
+ if (!isInRange(jankStat.frameVsyncId)) {
+ continue;
+ }
+ JankInfo info = findJankInfo(jankStat.frameVsyncId);
+ if (info != null) {
+ info.surfaceControlCallbackFired = true;
+ info.jankType = jankStat.jankType;
+ } else {
+ mJankInfos.put((int) jankStat.frameVsyncId,
+ JankInfo.createFromSurfaceControlCallback(
+ jankStat.frameVsyncId, jankStat.jankType));
+ }
+ }
+ processJankInfos();
+ }
+
+ private @Nullable JankInfo findJankInfo(long frameVsyncId) {
+ return mJankInfos.get((int) frameVsyncId);
+ }
+
+ private boolean isInRange(long vsyncId) {
+
+ // It's possible that we may miss a callback for the frame with vsyncId == mEndVsyncId.
+ // Because of that, we collect all frames even if they happen after the end so we eventually
+ // have a frame after the end with both callbacks present.
+ return vsyncId >= mBeginVsyncId;
}
@Override
@@ -121,60 +240,152 @@
// Since this callback might come a little bit late after the end() call.
// We should keep tracking the begin / end timestamp.
// Then compare with vsync timestamp to check if the frame is in the duration of the CUJ.
-
- long vsyncTimestamp = mMetricsWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP);
- // Discard the frame metrics which is not in the trace session.
- if (vsyncTimestamp < mBeginTime) return;
-
- // We stop getting callback when the vsync is later than the end calls.
- if (mEndTime != UNKNOWN_TIMESTAMP && vsyncTimestamp > mEndTime && !mSessionEnd) {
- mSessionEnd = true;
- // The tracing has been ended, remove the observer, see if need to trigger perfetto.
- mRendererWrapper.removeObserver(mObserver);
-
- // Log the frame stats as counters to make them easily accessible in traces.
- Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#sfMissedFrames",
- mSfMissedFramesCount);
- Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedFrames",
- mMissedFramesCount);
- Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#totalFrames",
- mTotalFramesCount);
- Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxFrameTimeMillis",
- (int) (mMaxFrameTimeNanos / NANOS_IN_MILLISECOND));
-
- // Trigger perfetto if necessary.
- boolean overMissedFramesThreshold = mTraceThresholdMissedFrames != -1
- && (mMissedFramesCount + mSfMissedFramesCount) >= mTraceThresholdMissedFrames;
- boolean overFrameTimeThreshold = mTraceThresholdFrameTimeMillis != -1
- && mMaxFrameTimeNanos >= mTraceThresholdFrameTimeMillis * NANOS_IN_MILLISECOND;
- if (overMissedFramesThreshold || overFrameTimeThreshold) {
- triggerPerfetto();
- }
- if (mSession.logToStatsd()) {
- FrameworkStatsLog.write(
- FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED,
- mSession.getStatsdInteractionType(),
- mTotalFramesCount,
- mMissedFramesCount,
- mMaxFrameTimeNanos,
- mSfMissedFramesCount);
- }
- return;
- }
-
long totalDurationNanos = mMetricsWrapper.getMetric(FrameMetrics.TOTAL_DURATION);
boolean isFirstFrame = mMetricsWrapper.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1;
- boolean isJankyFrame = !isFirstFrame && totalDurationNanos > JANK_THRESHOLD_NANOS;
+ long frameVsyncId = mMetricsWrapper.getTiming()[FrameMetrics.Index.FRAME_TIMELINE_VSYNC_ID];
- mTotalFramesCount += 1;
+ if (!isInRange(frameVsyncId)) {
+ return;
+ }
+ JankInfo info = findJankInfo(frameVsyncId);
+ if (info != null) {
+ info.hwuiCallbackFired = true;
+ info.totalDurationNanos = totalDurationNanos;
+ info.isFirstFrame = isFirstFrame;
+ } else {
+ mJankInfos.put((int) frameVsyncId, JankInfo.createFromHwuiCallback(
+ frameVsyncId, totalDurationNanos, isFirstFrame));
+ }
+ processJankInfos();
+ }
- if (!isFirstFrame) {
- mMaxFrameTimeNanos = Math.max(totalDurationNanos, mMaxFrameTimeNanos);
+ /**
+ * Finds the first index in {@link #mJankInfos} which happened on or after {@link #mEndVsyncId},
+ * or -1 if the session hasn't ended yet.
+ */
+ private int getIndexOnOrAfterEnd() {
+ if (mEndVsyncId == INVALID_ID || mMetricsFinalized) {
+ return -1;
+ }
+ JankInfo last = mJankInfos.size() == 0 ? null : mJankInfos.valueAt(mJankInfos.size() - 1);
+ if (last == null) {
+ return -1;
+ }
+ if (last.frameVsyncId < mEndVsyncId) {
+ return -1;
}
- // TODO(b/171049584): Also update mSfMissedFramesCount once the data is available.
- if (isJankyFrame) {
- mMissedFramesCount += 1;
+ int lastIndex = -1;
+ for (int i = mJankInfos.size() - 1; i >= 0; i--) {
+ JankInfo info = mJankInfos.valueAt(i);
+ if (info.frameVsyncId >= mEndVsyncId) {
+ if (info.hwuiCallbackFired && info.surfaceControlCallbackFired) {
+ lastIndex = i;
+ }
+ } else {
+ break;
+ }
+ }
+ return lastIndex;
+ }
+
+ private void processJankInfos() {
+ int indexOnOrAfterEnd = getIndexOnOrAfterEnd();
+ if (indexOnOrAfterEnd == -1) {
+ return;
+ }
+ finish(indexOnOrAfterEnd);
+ }
+
+ private void finish(int indexOnOrAfterEnd) {
+
+ mMetricsFinalized = true;
+
+ // The tracing has been ended, remove the observer, see if need to trigger perfetto.
+ removeObservers();
+
+ int totalFramesCount = 0;
+ long maxFrameTimeNanos = 0;
+ int missedAppFramesCount = 0;
+ int missedSfFramesCounts = 0;
+
+ for (int i = 0; i <= indexOnOrAfterEnd; i++) {
+ JankInfo info = mJankInfos.valueAt(i);
+ if (info.isFirstFrame) {
+ continue;
+ }
+ if (info.surfaceControlCallbackFired) {
+ totalFramesCount++;
+
+ // Only count missed frames if it's not stuffed.
+ if ((info.jankType & PREDICTION_ERROR) != 0
+ || ((info.jankType & JANK_APP_DEADLINE_MISSED) != 0
+ && (info.jankType & BUFFER_STUFFING) == 0)) {
+ Log.w(TAG, "Missed App frame:" + info.jankType);
+ missedAppFramesCount++;
+ }
+ if ((info.jankType & DISPLAY_HAL) != 0
+ || (info.jankType & JANK_SURFACEFLINGER_DEADLINE_MISSED) != 0
+ || (info.jankType & JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED) != 0
+ || (info.jankType & SURFACE_FLINGER_SCHEDULING) != 0) {
+ Log.w(TAG, "Missed SF frame:" + info.jankType);
+ missedSfFramesCounts++;
+ }
+ // TODO (b/174755489): Early latch currently gets fired way too often, so we have
+ // to ignore it for now.
+ if (!info.hwuiCallbackFired) {
+ Log.w(TAG, "Missing HWUI jank callback for vsyncId: " + info.frameVsyncId);
+ }
+ }
+ if (info.hwuiCallbackFired) {
+ maxFrameTimeNanos = Math.max(info.totalDurationNanos, maxFrameTimeNanos);
+ if (!info.surfaceControlCallbackFired) {
+ Log.w(TAG, "Missing SF jank callback for vsyncId: " + info.frameVsyncId);
+ }
+ }
+ }
+
+ // Log the frame stats as counters to make them easily accessible in traces.
+ Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedAppFrames",
+ missedAppFramesCount);
+ Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedSfFrames",
+ missedSfFramesCounts);
+ Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#totalFrames",
+ totalFramesCount);
+ Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#maxFrameTimeMillis",
+ (int) (maxFrameTimeNanos / NANOS_IN_MILLISECOND));
+
+ // Trigger perfetto if necessary.
+ boolean overMissedFramesThreshold = mTraceThresholdMissedFrames != -1
+ && missedAppFramesCount + missedSfFramesCounts >= mTraceThresholdMissedFrames;
+ boolean overFrameTimeThreshold = mTraceThresholdFrameTimeMillis != -1
+ && maxFrameTimeNanos >= mTraceThresholdFrameTimeMillis * NANOS_IN_MILLISECOND;
+ if (overMissedFramesThreshold || overFrameTimeThreshold) {
+ triggerPerfetto();
+ }
+ if (mSession.logToStatsd()) {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.UI_INTERACTION_FRAME_INFO_REPORTED,
+ mSession.getStatsdInteractionType(),
+ totalFramesCount,
+ missedAppFramesCount + missedSfFramesCounts,
+ maxFrameTimeNanos,
+ missedSfFramesCounts);
+ }
+ if (DEBUG) {
+ Log.i(TAG, "FrameTracker: CUJ=" + mSession.getName()
+ + " totalFrames=" + totalFramesCount
+ + " missedAppFrames=" + missedAppFramesCount
+ + " missedSfFrames=" + missedSfFramesCounts
+ + " maxFrameTimeMillis=" + maxFrameTimeNanos / NANOS_IN_MILLISECOND);
+ }
+ }
+
+ private void removeObservers() {
+ mRendererWrapper.removeObserver(mObserver);
+ mSurfaceControlWrapper.removeJankStatsListener(this);
+ if (mSurfaceChangedCallback != null) {
+ mViewRoot.removeSurfaceChangedCallback(mSurfaceChangedCallback);
}
}
@@ -189,7 +400,7 @@
* A wrapper class that we can spy FrameMetrics (a final class) in unit tests.
*/
public static class FrameMetricsWrapper {
- private FrameMetrics mFrameMetrics;
+ private final FrameMetrics mFrameMetrics;
public FrameMetricsWrapper() {
mFrameMetrics = new FrameMetrics();
@@ -217,7 +428,7 @@
* A wrapper class that we can spy ThreadedRenderer (a final class) in unit tests.
*/
public static class ThreadedRendererWrapper {
- private ThreadedRenderer mRenderer;
+ private final ThreadedRenderer mRenderer;
public ThreadedRendererWrapper(ThreadedRenderer renderer) {
mRenderer = renderer;
@@ -239,4 +450,49 @@
mRenderer.removeObserver(observer);
}
}
+
+ public static class ViewRootWrapper {
+ private final ViewRootImpl mViewRoot;
+
+ public ViewRootWrapper(ViewRootImpl viewRoot) {
+ mViewRoot = viewRoot;
+ }
+
+ public void addSurfaceChangedCallback(ViewRootImpl.SurfaceChangedCallback callback) {
+ mViewRoot.addSurfaceChangedCallback(callback);
+ }
+
+ public void removeSurfaceChangedCallback(ViewRootImpl.SurfaceChangedCallback callback) {
+ mViewRoot.removeSurfaceChangedCallback(callback);
+ }
+
+ public SurfaceControl getSurfaceControl() {
+ return mViewRoot.getSurfaceControl();
+ }
+ }
+
+ public static class SurfaceControlWrapper {
+
+ public void addJankStatsListener(SurfaceControl.OnJankDataListener listener,
+ SurfaceControl surfaceControl) {
+ SurfaceControl.addJankDataListener(listener, surfaceControl);
+ }
+
+ public void removeJankStatsListener(SurfaceControl.OnJankDataListener listener) {
+ SurfaceControl.removeJankDataListener(listener);
+ }
+ }
+
+ public static class ChoreographerWrapper {
+
+ private final Choreographer mChoreographer;
+
+ public ChoreographerWrapper(Choreographer choreographer) {
+ mChoreographer = choreographer;
+ }
+
+ public long getVsyncId() {
+ return mChoreographer.getVsyncId();
+ }
+ }
}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 1e2ce28..7c10a0a 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -16,6 +16,7 @@
package com.android.internal.jank;
+import static com.android.internal.jank.FrameTracker.*;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_HOME;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_CLOSE_TO_PIP;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_ICON;
@@ -42,11 +43,14 @@
import android.provider.DeviceConfig;
import android.util.Log;
import android.util.SparseArray;
+import android.view.Choreographer;
+import android.view.SurfaceControl;
import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
+import com.android.internal.jank.FrameTracker.ViewRootWrapper;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -125,13 +129,11 @@
private final DeviceConfig.OnPropertiesChangedListener mPropertiesChangedListener =
this::updateProperties;
- private ThreadedRendererWrapper mRenderer;
private FrameMetricsWrapper mMetrics;
private SparseArray<FrameTracker> mRunningTrackers;
private SparseArray<Runnable> mTimeoutActions;
private HandlerThread mWorker;
- private boolean mInitialized;
private boolean mEnabled = DEFAULT_ENABLED;
private int mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
private int mTraceThresholdMissedFrames = DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES;
@@ -188,43 +190,21 @@
mRunningTrackers = new SparseArray<>();
mTimeoutActions = new SparseArray<>();
mWorker = worker;
- }
+ mMetrics = new FrameMetricsWrapper();
+ mWorker.start();
+ mEnabled = DEFAULT_ENABLED;
+ mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
- /**
- * Init InteractionJankMonitor for later instrumentation.
- *
- * @param view Any view in the view tree to get context and ThreadedRenderer.
- * @return boolean true if the instance has been initialized successfully.
- */
- public boolean init(@NonNull View view) {
- if (!mInitialized) {
- synchronized (this) {
- if (!mInitialized) {
- if (!view.isAttachedToWindow()) {
- Log.d(TAG, "Expect an attached view!", new Throwable());
- return false;
- }
- mRenderer = new ThreadedRendererWrapper(view.getThreadedRenderer());
- mMetrics = new FrameMetricsWrapper();
- mWorker.start();
- mEnabled = DEFAULT_ENABLED;
- mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;
- mInitialized = true;
-
- // Post initialization to the background in case we're running on the main
- // thread.
- mWorker.getThreadHandler().post(
- () -> mPropertiesChangedListener.onPropertiesChanged(
- DeviceConfig.getProperties(
- DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR)));
- DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR,
- new HandlerExecutor(mWorker.getThreadHandler()),
- mPropertiesChangedListener);
- }
- }
- }
- return true;
+ // Post initialization to the background in case we're running on the main
+ // thread.
+ mWorker.getThreadHandler().post(
+ () -> mPropertiesChangedListener.onPropertiesChanged(
+ DeviceConfig.getProperties(
+ DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR)));
+ DeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR,
+ new HandlerExecutor(mWorker.getThreadHandler()),
+ mPropertiesChangedListener);
}
/**
@@ -234,37 +214,39 @@
* @return instance of the FrameTracker
*/
@VisibleForTesting
- public FrameTracker createFrameTracker(Session session) {
+ public FrameTracker createFrameTracker(View v, Session session) {
synchronized (this) {
- if (!mInitialized) return null;
- return new FrameTracker(session, mWorker.getThreadHandler(), mRenderer, mMetrics,
+ return new FrameTracker(session, mWorker.getThreadHandler(),
+ new ThreadedRendererWrapper(v.getThreadedRenderer()),
+ new ViewRootWrapper(v.getViewRootImpl()), new SurfaceControlWrapper(),
+ new ChoreographerWrapper(Choreographer.getInstance()), mMetrics,
mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis);
}
}
/**
- * Begin a trace session, must invoke {@link #init(View)} before invoking this method.
+ * Begin a trace session.
*
* @param cujType the specific {@link InteractionJankMonitor.CujType}.
* @return boolean true if the tracker is started successfully, false otherwise.
*/
- public boolean begin(@CujType int cujType) {
+ public boolean begin(View v, @CujType int cujType) {
synchronized (this) {
- return begin(cujType, DEFAULT_TIMEOUT_MS);
+ return begin(v, cujType, DEFAULT_TIMEOUT_MS);
}
}
/**
- * Begin a trace session, must invoke {@link #init(View)} before invoking this method.
+ * Begin a trace session.
*
* @param cujType the specific {@link InteractionJankMonitor.CujType}.
* @param timeout the elapsed time in ms until firing the timeout action.
* @return boolean true if the tracker is started successfully, false otherwise.
*/
- public boolean begin(@CujType int cujType, long timeout) {
+ public boolean begin(View v, @CujType int cujType, long timeout) {
synchronized (this) {
- if (!mInitialized) {
- Log.d(TAG, "Not initialized!", new Throwable());
+ if (!v.isAttachedToWindow()) {
+ Log.d(TAG, "View not attached!", new Throwable());
return false;
}
boolean shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
@@ -276,7 +258,7 @@
if (tracker != null) return false;
// begin a new trace session.
- tracker = createFrameTracker(new Session(cujType));
+ tracker = createFrameTracker(v, new Session(cujType));
mRunningTrackers.put(cujType, tracker);
tracker.begin();
@@ -289,7 +271,7 @@
}
/**
- * End a trace session, must invoke {@link #init(View)} before invoking this method.
+ * End a trace session.
*
* @param cujType the specific {@link InteractionJankMonitor.CujType}.
* @return boolean true if the tracker is ended successfully, false otherwise.
@@ -297,10 +279,7 @@
public boolean end(@CujType int cujType) {
//TODO (163505250): This should be no-op if not in droid food rom.
synchronized (this) {
- if (!mInitialized) {
- Log.d(TAG, "Not initialized!", new Throwable());
- return false;
- }
+
// remove the timeout action first.
Runnable timeout = mTimeoutActions.get(cujType);
if (timeout != null) {
@@ -318,17 +297,13 @@
}
/**
- * Cancel the trace session, must invoke {@link #init(View)} before invoking this method.
+ * Cancel the trace session.
*
* @return boolean true if the tracker is cancelled successfully, false otherwise.
*/
public boolean cancel(@CujType int cujType) {
//TODO (163505250): This should be no-op if not in droid food rom.
synchronized (this) {
- if (!mInitialized) {
- Log.d(TAG, "Not initialized!", new Throwable());
- return false;
- }
// remove the timeout action first.
Runnable timeout = mTimeoutActions.get(cujType);
if (timeout != null) {
@@ -347,7 +322,6 @@
private FrameTracker getTracker(@CujType int cuj) {
synchronized (this) {
- if (!mInitialized) return null;
return mRunningTrackers.get(cuj);
}
}
@@ -376,7 +350,6 @@
@VisibleForTesting
public void trigger(Session session) {
synchronized (this) {
- if (!mInitialized) return;
mWorker.getThreadHandler().post(
() -> PerfettoTrigger.trigger(session.getPerfettoTrigger()));
}
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index c0648ab..2e7629a 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -129,7 +129,7 @@
String[] routes = routesStr.trim().split(" ");
for (String route : routes) {
//each route is ip/prefix
- RouteInfo info = new RouteInfo(new IpPrefix(route), null);
+ RouteInfo info = new RouteInfo(new IpPrefix(route), null, null, RouteInfo.RTN_UNICAST);
this.routes.add(info);
updateAllowedFamilies(info.getDestination().getAddress());
}
diff --git a/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java b/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java
new file mode 100644
index 0000000..fa552e3
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+/**
+ * Reads total CPU time bpf map.
+ */
+public final class KernelCpuTotalBpfMapReader {
+ private KernelCpuTotalBpfMapReader() {
+ }
+
+ /** Returns whether total CPU time is measured. */
+ public static boolean isSupported() {
+ // TODO(b/174245730): Implement this check.
+ return true;
+ }
+
+ /** Reads total CPU time from bpf map. */
+ public static native boolean read(Callback callback);
+
+ /** Callback accepting values read from bpf map. */
+ public interface Callback {
+ /**
+ * Accepts values read from bpf map: cluster index, frequency in kilohertz and time in
+ * milliseconds that the cpu cluster spent at the frequency (excluding sleep).
+ */
+ void accept(int cluster, int freqKhz, long timeMs);
+ }
+}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 4512fba..adebde0 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2019,6 +2019,7 @@
if (getForeground() != null) {
drawableChanged();
}
+ notifyCaptionHeightChanged();
}
}
diff --git a/core/java/com/android/internal/util/LocationPermissionChecker.java b/core/java/com/android/internal/util/LocationPermissionChecker.java
index 59c0c00..d67bd7a 100644
--- a/core/java/com/android/internal/util/LocationPermissionChecker.java
+++ b/core/java/com/android/internal/util/LocationPermissionChecker.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.LocationManager;
+import android.net.NetworkStack;
import android.os.Binder;
import android.os.Build;
import android.os.UserHandle;
@@ -147,6 +148,13 @@
int uid, @Nullable String message) {
checkPackage(uid, pkgName);
+ // Apps with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD, NETWORK_STACK & MAINLINE_NETWORK_STACK
+ // are granted a bypass.
+ if (checkNetworkSettingsPermission(uid) || checkNetworkSetupWizardPermission(uid)
+ || checkNetworkStackPermission(uid) || checkMainlineNetworkStackPermission(uid)) {
+ return SUCCEEDED;
+ }
+
// Location mode must be enabled
if (!isLocationModeEnabled()) {
return ERROR_LOCATION_MODE_OFF;
@@ -259,4 +267,37 @@
// We don't care about pid, pass in -1
return mContext.checkPermission(permissionType, -1, uid);
}
+
+ /**
+ * Returns true if the |uid| holds NETWORK_SETTINGS permission.
+ */
+ public boolean checkNetworkSettingsPermission(int uid) {
+ return getUidPermission(android.Manifest.permission.NETWORK_SETTINGS, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ /**
+ * Returns true if the |uid| holds NETWORK_SETUP_WIZARD permission.
+ */
+ public boolean checkNetworkSetupWizardPermission(int uid) {
+ return getUidPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ /**
+ * Returns true if the |uid| holds NETWORK_STACK permission.
+ */
+ public boolean checkNetworkStackPermission(int uid) {
+ return getUidPermission(android.Manifest.permission.NETWORK_STACK, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ /**
+ * Returns true if the |uid| holds MAINLINE_NETWORK_STACK permission.
+ */
+ public boolean checkMainlineNetworkStackPermission(int uid) {
+ return getUidPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
}
diff --git a/core/java/com/android/internal/widget/OWNERS b/core/java/com/android/internal/widget/OWNERS
index cca39ea..ae566c3 100644
--- a/core/java/com/android/internal/widget/OWNERS
+++ b/core/java/com/android/internal/widget/OWNERS
@@ -1 +1,7 @@
per-file PointerLocationView.java = michaelwr@google.com, svv@google.com
+
+# LockSettings related
+per-file *LockPattern* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *LockScreen* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *Lockscreen* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *LockSettings* = file:/services/core/java/com/android/server/locksettings/OWNERS
diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java
index 93f89b5..139b88b 100644
--- a/core/java/com/android/server/net/BaseNetworkObserver.java
+++ b/core/java/com/android/server/net/BaseNetworkObserver.java
@@ -64,7 +64,7 @@
}
@Override
- public void interfaceClassDataActivityChanged(int networkType, boolean active, long tsNanos,
+ public void interfaceClassDataActivityChanged(int transportType, boolean active, long tsNanos,
int uid) {
// default no-op
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 94ef64f..0b48e72 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -184,6 +184,7 @@
"com_android_internal_net_NetworkUtilsInternal.cpp",
"com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
+ "com_android_internal_os_KernelCpuTotalBpfMapReader.cpp",
"com_android_internal_os_KernelCpuUidBpfMapReader.cpp",
"com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp",
"com_android_internal_os_KernelSingleUidTimeReader.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index cefa88c..8879111 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -190,6 +190,7 @@
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
+extern int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env);
extern int register_com_android_internal_os_KernelSingleProcessCpuThreadReader(JNIEnv* env);
extern int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env);
@@ -1585,6 +1586,7 @@
REG_JNI(register_android_security_Scrypt),
REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
REG_JNI(register_com_android_internal_os_FuseAppLoop),
+ REG_JNI(register_com_android_internal_os_KernelCpuTotalBpfMapReader),
REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader),
REG_JNI(register_com_android_internal_os_KernelSingleProcessCpuThreadReader),
REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader),
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 302ac3c..8dc56ed 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -1946,7 +1946,7 @@
jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
- nAudioMix->mAllowPrivilegedPlaybackCapture =
+ nAudioMix->mAllowPrivilegedMediaPlaybackCapture =
env->GetBooleanField(jRule, gAudioMixingRuleFields.mAllowPrivilegedPlaybackCapture);
nAudioMix->mVoiceCommunicationCaptureAllowed =
env->GetBooleanField(jRule, gAudioMixingRuleFields.mVoiceCommunicationCaptureAllowed);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a6dbd19..b8e1807 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -26,11 +26,11 @@
#include <android-base/chrono_utils.h>
#include <android/graphics/region.h>
+#include <android/gui/BnScreenCaptureListener.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_view_SurfaceSession.h>
-#include <gui/IScreenCaptureListener.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
@@ -51,8 +51,8 @@
#include <ui/HdrCapabilities.h>
#include <ui/Rect.h>
#include <ui/Region.h>
-#include <utils/Log.h>
#include <utils/LightRefBase.h>
+#include <utils/Log.h>
// ----------------------------------------------------------------------------
@@ -247,7 +247,7 @@
}
}
-class ScreenCaptureListenerWrapper : public BnScreenCaptureListener {
+class ScreenCaptureListenerWrapper : public gui::BnScreenCaptureListener {
public:
explicit ScreenCaptureListenerWrapper(JNIEnv* env, jobject jobject) {
env->GetJavaVM(&mVm);
@@ -262,12 +262,13 @@
}
}
- status_t onScreenCaptureComplete(const ScreenCaptureResults& captureResults) override {
+ binder::Status onScreenCaptureComplete(
+ const gui::ScreenCaptureResults& captureResults) override {
JNIEnv* env = getenv();
if (captureResults.result != NO_ERROR || captureResults.buffer == nullptr) {
env->CallVoidMethod(screenCaptureListenerObject,
gScreenCaptureListenerClassInfo.onScreenCaptureComplete, nullptr);
- return NO_ERROR;
+ return binder::Status::ok();
}
jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer(
env, captureResults.buffer->toAHardwareBuffer());
@@ -283,7 +284,7 @@
screenshotHardwareBuffer);
env->DeleteLocalRef(jhardwareBuffer);
env->DeleteLocalRef(screenshotHardwareBuffer);
- return NO_ERROR;
+ return binder::Status::ok();
}
private:
@@ -1662,21 +1663,22 @@
if (surface == nullptr) {
return;
}
- JankDataListenerWrapper* wrapper =
+ sp<JankDataListenerWrapper> wrapper =
reinterpret_cast<JankDataListenerWrapper*>(jankDataCallbackListenerPtr);
TransactionCompletedListener::getInstance()->addJankListener(wrapper, surface);
}
static void nativeRemoveJankDataListener(JNIEnv* env, jclass clazz,
jlong jankDataCallbackListenerPtr) {
- JankDataListenerWrapper* wrapper =
+ sp<JankDataListenerWrapper> wrapper =
reinterpret_cast<JankDataListenerWrapper*>(jankDataCallbackListenerPtr);
TransactionCompletedListener::getInstance()->removeJankListener(wrapper);
}
static jlong nativeCreateJankDataListenerWrapper(JNIEnv* env, jclass clazz,
jobject jankDataListenerObject) {
- return reinterpret_cast<jlong>(new JankDataListenerWrapper(env, jankDataListenerObject));
+ return reinterpret_cast<jlong>(
+ new JankDataListenerWrapper(env, jankDataListenerObject));
}
static jint nativeGetGPUContextPriority(JNIEnv* env, jclass clazz) {
diff --git a/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp b/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp
new file mode 100644
index 0000000..7249238
--- /dev/null
+++ b/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include "core_jni_helpers.h"
+
+#include <cputimeinstate.h>
+
+namespace android {
+
+static jboolean KernelCpuTotalBpfMapReader_read(JNIEnv *env, jobject, jobject callback) {
+ jclass callbackClass = env->GetObjectClass(callback);
+ jmethodID callbackMethod = env->GetMethodID(callbackClass, "accept", "(IIJ)V");
+ if (callbackMethod == 0) {
+ return JNI_FALSE;
+ }
+
+ auto freqs = android::bpf::getCpuFreqs();
+ if (!freqs) return JNI_FALSE;
+ auto freqTimes = android::bpf::getTotalCpuFreqTimes();
+ if (!freqTimes) return JNI_FALSE;
+
+ auto freqsClusterSize = (*freqs).size();
+ for (uint32_t clusterIndex = 0; clusterIndex < freqsClusterSize; ++clusterIndex) {
+ auto freqsSize = (*freqs)[clusterIndex].size();
+ for (uint32_t freqIndex = 0; freqIndex < freqsSize; ++freqIndex) {
+ env->CallVoidMethod(callback, callbackMethod, clusterIndex,
+ (*freqs)[clusterIndex][freqIndex],
+ (*freqTimes)[clusterIndex][freqIndex] / 1000000);
+ }
+ }
+ return JNI_TRUE;
+}
+
+static const JNINativeMethod methods[] = {
+ {"read", "(Lcom/android/internal/os/KernelCpuTotalBpfMapReader$Callback;)Z",
+ (void *)KernelCpuTotalBpfMapReader_read},
+};
+
+int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, "com/android/internal/os/KernelCpuTotalBpfMapReader", methods,
+ NELEM(methods));
+}
+
+} // namespace android
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 2ff474b..4dc8121 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1784,7 +1784,7 @@
heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
break;
}
- android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level));
+ mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level);
// Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime.
runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ce3ed9d..b705a01 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2676,11 +2676,24 @@
The app can check whether it has this authorization by calling
{@link android.provider.Settings#canDrawOverlays
Settings.canDrawOverlays()}.
- <p>Protection level: signature|appop|installer|pre23|development -->
+ <p>Protection level: signature|appop|preinstalled|pre23|development -->
<permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
android:label="@string/permlab_systemAlertWindow"
android:description="@string/permdesc_systemAlertWindow"
- android:protectionLevel="signature|appop|installer|pre23|development" />
+ android:protectionLevel="signature|appop|preinstalled|pre23|development" />
+
+ <!-- @SystemApi @hide Allows an application to create windows using the type
+ {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY},
+ shown on top of all other apps.
+
+ Allows an application to use
+ {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY}
+ to create overlays that will stay visible, even if another window is requesting overlays to
+ be hidden through {@link android.view.Window#setHideOverlayWindows(boolean)}.
+
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY"
+ android:protectionLevel="signature|wellbeing"/>
<!-- @deprecated Use {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND}
@hide
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 02cf0b7..a30111b 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -1,7 +1,9 @@
adamp@google.com
alanv@google.com
+asc@google.com
dsandler@android.com
dsandler@google.com
+dupin@google.com
hackbod@android.com
hackbod@google.com
jsharkey@android.com
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index cef5e1c..bd017fd 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Inkomender beller-ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Uitgaande beller-ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID van gekoppelde lyn"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Beperking op ID van gekoppelde lyn"</string>
<string name="CfMmi" msgid="8390012691099787178">"Oproepaanstuur"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Bel oor Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Bel oor mobiele netwerk"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Net Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g>-oorkruis-SIM-oproepe"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nie aangestuur nie"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> na <xliff:g id="TIME_DELAY">{2}</xliff:g> sekondes"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 0d3939b..4955e47 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"የገቢ ደዋይID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"የወጪ ጥሪID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"የተገናኘ መስመር መታወቂያ"</string>
<string name="ColrMmi" msgid="5889782479745764278">"የተገናኘ መስመር መታወቂያ ገደብ"</string>
<string name="CfMmi" msgid="8390012691099787178">"ጥሪ ማስተላለፍ"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"በ Wi-Fi በኩል ደውል"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ከተንቀሳቃሽ ስልክ አውታረ መረብ በኩል ደውል"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi ብቻ"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> የሲም መካከል የሚደረግ ጥሪ"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡አልተላለፈም"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>፡<xliff:g id="DIALING_NUMBER">{1}</xliff:g> ከ<xliff:g id="TIME_DELAY">{2}</xliff:g> ሰከንዶች በኋላ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 3a4518e..770c304 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -61,7 +61,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"معرف المتصل الوارد"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"معرف المتصل الصادر"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"معرّف الخط المتصل"</string>
<string name="ColrMmi" msgid="5889782479745764278">"تقييد معرّف الخط المتصل"</string>
<string name="CfMmi" msgid="8390012691099787178">"إعادة توجيه المكالمة"</string>
@@ -150,6 +151,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"الاتصال عبر Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"الاتصال عبر شبكة الجوّال"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi فقط"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> الاتصال عبر شرائح SIM"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: لم تتم إعادة التوجيه"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانية"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 3adb318..2e23ee4 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"অন্তৰ্গামী কলাৰ আইডি"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"বহিৰ্গামী কলাৰ আইডি"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"সংযোজিত লাইন আইডি"</string>
<string name="ColrMmi" msgid="5889782479745764278">"সংযোজিত লাইন আইডিৰ সীমাবদ্ধতা"</string>
<string name="CfMmi" msgid="8390012691099787178">"কল ফৰৱাৰ্ডিং"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"ৱাই-ফাইৰ জৰিয়তে কল কৰক"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ম’বাইল নেটৱৰ্কৰ জৰিয়তে কল কৰক"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"কোৱল ৱাই-ফাই"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> ক্ৰছ-ছিম কলিং"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফৰৱাৰ্ড কৰা নহ\'ল"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ছেকেণ্ডৰ পাছত"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index a223715..475fa7d 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Gələn çağrı kimliyi"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Gedən çağrı kimliyi"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Qoşulmuş Xətt ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Qoşulmuş Xətt ID Məhdudluğu"</string>
<string name="CfMmi" msgid="8390012691099787178">"Zəng yönləndirmə"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi ilə zəng edin"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Mobil şəbəkə ilə zəng edin"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Yalnız Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Çarpaz SİM Zəngi"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönləndirilmədi"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> saniyə sonra"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index aa7f658..6378045 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -58,7 +58,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Dolazni ID pozivaoca"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Odlazni ID pozivaoca"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID povezane linije"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Ograničenje ID-a povezane linije"</string>
<string name="CfMmi" msgid="8390012691099787178">"Preusmeravanje poziva"</string>
@@ -147,6 +148,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Pozivanje preko WiFi-a"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Poziv preko mobilne mreže"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Samo WiFi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Pozivi sa više SIM kartica za operatera <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunde/i"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 8cc58a1..80c071c 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Ідэнтыфікатар АВН"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Ідэнтыфікатар АВН"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Ідэнтыфікатар падлучанай лініі"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Абмежаванне ідэнтыфікатара падлучанай лініі"</string>
<string name="CfMmi" msgid="8390012691099787178">"Пераадрасацыя выкліку"</string>
@@ -148,6 +149,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Выклікаць праз Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Выклікаць праз мабільную сетку"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Толькі Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Тэлефанія паміж SIM-картамі"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не пераадрасоўваецца"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> праз <xliff:g id="TIME_DELAY">{2}</xliff:g> с."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index ec29f3e..6dd7b6a6 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Идентификация на вх. обаждания"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Идентификация на изходящите повиквания"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Идентификация на свързаната линия"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Ограничение за идентификацията на свързаната линия"</string>
<string name="CfMmi" msgid="8390012691099787178">"Пренасочване на повиквания"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Обаждане през Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Обаждане през мобилна мрежа"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Само Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Обаждания през друга SIM карта от <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Не е пренасочено"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> след <xliff:g id="TIME_DELAY">{2}</xliff:g> секунди"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 8dced4b2..ff9b003 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"আগত কলার আইডি"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"আউটগোয়িং কলার আইডি"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"সংযুক্ত লাইন ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"সংযুক্ত লাইন ID-র বিধিনিষেধ"</string>
<string name="CfMmi" msgid="8390012691099787178">"কল ফরওয়ার্ড করা"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"ওয়াই-ফাইয়ের মাধ্যমে কল করুন"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"মোবাইল নেটওয়ার্কের মাধ্যমে কল করুন"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"শুধুমাত্র ওয়াই-ফাই"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> ক্রস সিম কল করা"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ফরওয়ার্ড করা হয়নি"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> সেকেন্ড পরে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 64b785a..d2a4f7d 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -58,7 +58,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID dolaznog poziva"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID odlaznog poziva"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Identifikacija povezane linije"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Ograničenje identifikacije povezane linije"</string>
<string name="CfMmi" msgid="8390012691099787178">"Prosljeđivanje poziva"</string>
@@ -147,6 +148,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Poziv putem WiFi-ja"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Poziv putem mobilne mreže"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Samo WiFi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> – pozivanje na različitim SIM-ovima"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije proslijeđen"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> za <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundi"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 17a5039..47be220 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Identificador de trucada (trucada entrant)"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Identificador de trucada (trucada de sortida)"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Identificador de la línia connectada"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restricció de l\'identificador de la línia connectada"</string>
<string name="CfMmi" msgid="8390012691099787178">"Desviació de trucades"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Trucades per Wi‑Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Trucades per la xarxa mòbil"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Només Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Trucades entre targetes SIM de l\'operador <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no s\'ha desviat"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> després de <xliff:g id="TIME_DELAY">{2}</xliff:g> segons"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index e51ec22..e7e4cc9 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Příchozí ID volajícího"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Odchozí ID volajícího"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID připojené linky"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Omezení ID připojené linky"</string>
<string name="CfMmi" msgid="8390012691099787178">"Přesměrování hovorů"</string>
@@ -148,6 +149,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Volání přes Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Volání přes mobilní síť"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Pouze Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> – volání napříč SIM kartami"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepřesměrováno"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sek."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 19add07..47416cf 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI-nummer"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Indgående opkalds-id"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Udgående opkalds-id"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Id for opkaldsmodtager"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Id for opkaldsmodtager er skjult"</string>
<string name="CfMmi" msgid="8390012691099787178">"Viderestilling af opkald"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Ring via Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Ring via mobilnetværk"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Kun Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Opkald på tværs af SIM-kort"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderestillet"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 410b597..54e9dfd 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Anrufer-ID für eingehenden Anruf"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Anrufer-ID für ausgehenden Anruf"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID der verbundenen Leitung"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Beschränkung für ID der verbundenen Leitung"</string>
<string name="CfMmi" msgid="8390012691099787178">"Rufweiterleitung"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Anruf über WLAN"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Über Mobilfunknetz anrufen"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Nur WLAN"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nicht weitergeleitet"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> nach <xliff:g id="TIME_DELAY">{2}</xliff:g> Sekunden."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 7427216..b759be6 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Εισερχόμενη αναγνώριση κλήσης"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Εξερχόμενη αναγνώριση κλήσης"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Αναγνωριστικό συνδεδεμένης γραμμής"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Περιορισμός αναγνωριστικού συνδεδεμένης πρόσβασης"</string>
<string name="CfMmi" msgid="8390012691099787178">"Προώθηση κλήσεων"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Κλήση μέσω Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Κλήση μέσω δικτύου κινητής τηλεφωνίας"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Μόνο Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Κλήση με πολλές SIM <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Δεν προωθήθηκε"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> μετά από <xliff:g id="TIME_DELAY">{2}</xliff:g> δευτερόλεπτα"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index ae324be..7c7c178 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Incoming Caller ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Outgoing Caller ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Connected Line ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Connected Line ID Restriction"</string>
<string name="CfMmi" msgid="8390012691099787178">"Call forwarding"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Call over Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Call over mobile network"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi only"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Cross-SIM calling"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 630a243..0cbbb01 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Incoming Caller ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Outgoing Caller ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Connected Line ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Connected Line ID Restriction"</string>
<string name="CfMmi" msgid="8390012691099787178">"Call forwarding"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Call over Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Call over mobile network"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi only"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Cross-SIM calling"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 1a8f5c0..e923d65 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Incoming Caller ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Outgoing Caller ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Connected Line ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Connected Line ID Restriction"</string>
<string name="CfMmi" msgid="8390012691099787178">"Call forwarding"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Call over Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Call over mobile network"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi only"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Cross-SIM calling"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 6503267..6e17242 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Incoming Caller ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Outgoing Caller ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Connected Line ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Connected Line ID Restriction"</string>
<string name="CfMmi" msgid="8390012691099787178">"Call forwarding"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Call over Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Call over mobile network"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi only"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Cross-SIM calling"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 0d0b204..759fe01 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Incoming Caller ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Outgoing Caller ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Connected Line ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Connected Line ID Restriction"</string>
<string name="CfMmi" msgid="8390012691099787178">"Call forwarding"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Call over Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Call over mobile network"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi only"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Cross-SIM Calling"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Not forwarded"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> after <xliff:g id="TIME_DELAY">{2}</xliff:g> seconds"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 1128479..64bc3d1 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Identificador de llamadas entrantes"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Identificador de llamadas salientes"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID de línea conectada"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restricción de ID de línea conectada"</string>
<string name="CfMmi" msgid="8390012691099787178">"Desvío de llamadas"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Llamar mediante Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Llamar mediante red móvil"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Solo Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Llamadas entre tarjetas SIM de <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: no se ha remitido"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> después de <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 366c506..08555e8 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID de emisor de llamada entrante"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID de emisor de llamada saliente"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID de línea conectada"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restricción de ID de línea conectada"</string>
<string name="CfMmi" msgid="8390012691099787178">"Desvío de llamadas"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Llamar a través de la red Wi‑Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Llamar a través de la red móvil"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Solo Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Llamadas entre tarjetas SIM de <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: No desviada"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> transcurridos <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index d585452..4818589 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Sissetuleva kõne helistaja ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Väljuva kõne helistaja ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Ühendatud liini ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Ühendatud liini ID piiramine"</string>
<string name="CfMmi" msgid="8390012691099787178">"Kõnede suunamine"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Helista WiFi kaudu"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Helista mobiilsidevõrgu kaudu"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Ainult WiFi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> – helistamine mitme SIM-kaardi kaudu"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: pole suunatud"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundi pärast"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 4ba95bb..39fc77c 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI zk."</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Sarrerako deien identifikazio-zerbitzua"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Irteerako deien identifikazio-zerbitzua"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Konektatutako linearen IDa"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Konektatutako linearen ID murriztapena"</string>
<string name="CfMmi" msgid="8390012691099787178">"Dei-desbideratzea"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Deitu wifi bidez"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Deitu sare mugikorraren bidez"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wifi-sarea soilik"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> operadorearen beste SIM txartel batetik deitzeko aukera"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ez da desbideratu"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> zenbakira <xliff:g id="TIME_DELAY">{2}</xliff:g> segundotan"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 4c75ac5..935d679 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"شناسه تماسگیرنده ورودی"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"شناسه تماسگیرنده خروجی"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"شناسه خط متصل"</string>
<string name="ColrMmi" msgid="5889782479745764278">"محدودیت شناسه خط متصل"</string>
<string name="CfMmi" msgid="8390012691099787178">"هدایت تماس"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"تماس ازطریق Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"تماس ازطریق شبکه تلفن همراه"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"فقط Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"تماس بین سیمکارت <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: هدایت نشده"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> پس از <xliff:g id="TIME_DELAY">{2}</xliff:g> ثانیه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 93b5ff1..09f289a 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI-koodi"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Soittajan tunnus"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Soittajan tunnus"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Yhteyslinjan tunnus"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Yhteyslinjan tunnuksen rajoitus"</string>
<string name="CfMmi" msgid="8390012691099787178">"Soitonsiirto"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Soita Wi-Fin kautta"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Soita mobiiliverkon kautta"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Vain Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"SIM-korttien väliset puhelut: <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ei siirretty"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunnin päästä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index d3329d3..6bedfca 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"Code IIEM"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Numéro de l\'appelant (entrant)"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Numéro de l\'appelant (sortant)"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Identifiant de la ligne connectée"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restriction d\'identifiant de la ligne connectée"</string>
<string name="CfMmi" msgid="8390012691099787178">"Transfert d\'appel"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Appels par Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Appels sur réseau cellulaire"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi seulement"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Appels multiSIM avec <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 6c07066..d8edc5d 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"Code IMEI"</string>
<string name="meid" msgid="3291227361605924674">"Code MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Numéro de l\'appelant (entrant)"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Numéro de l\'appelant (sortant)"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Identifiant de la ligne connectée"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restriction d\'identifiant de la ligne connectée"</string>
<string name="CfMmi" msgid="8390012691099787178">"Transfert d\'appel"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Appel via le Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Appel via le réseau mobile"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi uniquement"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Appels par cartes SIM croisées <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g> au bout de <xliff:g id="TIME_DELAY">{2}</xliff:g> secondes"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index cab106ac..76ab6ab 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Identificador de chamada entrante"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Identificador de chamada saínte"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID de liña conectada"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restrición de ID de liña conectada"</string>
<string name="CfMmi" msgid="8390012691099787178">"Desvío de chamadas"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Chama por wifi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Chama pola rede de telefonía móbil"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Só por wifi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Chamadas doutra SIM a través desta (<xliff:g id="SPN">%s</xliff:g>)"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: non desviada"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> tras <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 016e77b..a591d31 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"આવનાર કૉલર ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"આઉટગોઇંગ કૉલર ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"કનેક્ટ કરેલ લાઇન ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"કનેક્ટ કરેલ લાઇન ID પ્રતિબંધ"</string>
<string name="CfMmi" msgid="8390012691099787178">"કૉલ ફોર્વર્ડિંગ"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"વાઇ-ફાઇ પરથી કૉલ કરો"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"મોબાઇલ નેટવર્ક પરથી કૉલ કરો"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"ફક્ત વાઇ-ફાઇ"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ફોરવર્ડ કર્યો નથી"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="TIME_DELAY">{2}</xliff:g> સેકન્ડ પછી <xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index a8afbbe..a094117 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"आईएमईआई"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"इनकमिंग कॉलर आईडी"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"आउटगोइंग कॉलर आईडी"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"कनेक्ट किया गया लाइन आईडी"</string>
<string name="ColrMmi" msgid="5889782479745764278">"कनेक्ट किया गया लाइन आईडी प्रतिबंध"</string>
<string name="CfMmi" msgid="8390012691099787178">"कॉल आगे भेजना"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"वाई-फ़ाई के ज़रिए कॉल करें"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"मोबाइल नेटवर्क के ज़रिए कॉल"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"केवल वाई-फ़ाई"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> क्रॉस सिम कॉलिंग"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित नहीं किया गया"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंड के बाद"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 625b3ed..aebab8c 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -58,7 +58,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID dolaznog pozivatelja"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID izlaznog pozivatelja"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID povezane linije"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Ograničenje ID-a povezane linije"</string>
<string name="CfMmi" msgid="8390012691099787178">"Preusmjeravanje poziva"</string>
@@ -147,6 +148,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Pozivi putem Wi-Fija"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Pozivi putem mobilne mreže"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Samo Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Preusmjeravanje poziva na drugi SIM"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije proslijeđeno"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> s"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 551043e..efdf842 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Beérkező hívóazonosító"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Kimenő hívóazonosító"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Összekapcsolt sorazonosító"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Összekapcsolt sorazonosító korlátozása"</string>
<string name="CfMmi" msgid="8390012691099787178">"Hívásátirányítás"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Hívás Wi-Fi-hálózaton"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Hívás mobilhálózaton"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Csak Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> SIM-eken keresztüli hívás"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nincs átirányítva"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> másodperc után"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index f08c7f9..29803b8 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Մուտքային զանգողի ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Ելքային զանգողի ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Կապված տողի ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Կապված տողի ID-ի սահմանափակում"</string>
<string name="CfMmi" msgid="8390012691099787178">"Զանգի վերահասցեավորում"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Զանգ Wi-Fi-ի միջոցով"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Զանգ բջջային ցանցի միջոցով"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Միայն Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> SIM քարտերով խաչաձև զանգեր"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. Չի վերահասցեավորվել"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>. <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> վայրկյանից"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index a7a7cb8..510621b 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Nomor Penelepon Masuk"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Nomor Penelepon Keluar"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID Saluran yang Tersambung"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Batasan ID Saluran yang Tersambung"</string>
<string name="CfMmi" msgid="8390012691099787178">"Penerusan panggilan"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Panggilan telepon melalui Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Panggilan telepon melalui jaringan seluler"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Khusus Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Panggilan Lintas-SIM <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak diteruskan"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> setelah <xliff:g id="TIME_DELAY">{2}</xliff:g> detik"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 2ca613c..802feeeb 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Númerabirting innhringinga"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Númerabirting úthringinga"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Auðkenni tengdrar línu"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Auðkennistakmörkun tengdrar línu"</string>
<string name="CfMmi" msgid="8390012691099787178">"Símtalsflutningur"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Hringja í gegnum Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Hringja í gegnum farsímakerfi"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi eingöngu"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Skipt á milli SIM-korta"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ekki áframsent"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> eftir <xliff:g id="TIME_DELAY">{2}</xliff:g> sekúndur"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 4f7eea8..2c01776 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID chiamante in entrata"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID chiamante in uscita"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID linea connessa"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Limitazione ID linea connessa"</string>
<string name="CfMmi" msgid="8390012691099787178">"Deviazione chiamate"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Chiamata tramite Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Chiamata su rete mobile"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Solo Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Chiamate tramite più SIM <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: inoltro non effettuato"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> dopo <xliff:g id="TIME_DELAY">{2}</xliff:g> secondi"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index be3e3c75..2bdabc8 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"זיהוי מתקשר של שיחה נכנסת"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"זיהוי מתקשר בשיחה יוצאת"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"מזהה של קו מחובר"</string>
<string name="ColrMmi" msgid="5889782479745764278">"הגבלה של מזהה קו מחובר"</string>
<string name="CfMmi" msgid="8390012691099787178">"העברת שיחות"</string>
@@ -148,6 +149,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"שיחה בחיבור Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"שיחה ברשת סלולרית"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi בלבד"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ללא העברה"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> כעבור <xliff:g id="TIME_DELAY">{2}</xliff:g> שניות"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 658237d..cf493c0 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"着信時の発信者番号"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"発信者番号"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"接続回線ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"接続回線IDの制限"</string>
<string name="CfMmi" msgid="8390012691099787178">"着信転送"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi 経由で通話"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"モバイル ネットワーク経由で通話"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fiのみ"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Cross-SIM 通話"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転送できません"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g> (<xliff:g id="TIME_DELAY">{2}</xliff:g>秒後)"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 6d9c12b..9de08bc 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"შემომავალი ზარის აბონენტის ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"გამავალი მრეკავის ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"დაუკავშირდა Line ID-ს"</string>
<string name="ColrMmi" msgid="5889782479745764278">"დაუკავშირდა Line ID Restriction-ს"</string>
<string name="CfMmi" msgid="8390012691099787178">"ზარის გადამისამართება"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"დარეკვა Wi-Fi-ის მეშვეობით"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"დარეკვა მობილური ქსელის მეშვეობით"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"მხოლოდ Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> SIM-თაშორისი დარეკვა"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: არ არის გადამისამართებული"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> წამის შემდეგ"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index d57aca5..f38be01 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI (Халықаралық мобильдік құрылғы анықтағышы)"</string>
<string name="meid" msgid="3291227361605924674">"MEID (ұялы құрылғы анықтағыш)"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Келген қоңырау шалушының жеке анықтағышы"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Шыққан қоңырау шалушының жеке анықтағышы"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Қосылған желі идентификаторы"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Қосылған желі идентификаторын шектеу"</string>
<string name="CfMmi" msgid="8390012691099787178">"Қоңырауды басқа нөмірге бағыттау"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi арқылы қоңырау шалу"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Мобильдік желі арқылы қоңырау шалу"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Тек Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> SIM карталары арасында қоңырау шалу"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Басқа нөмірге бағытталмады"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секундтан кейін"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 362b7c0..2a70449 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"លេខសម្គាល់អ្នកហៅចូល"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"លេខសម្គាល់អ្នកហៅចេញ"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"បានភ្ជាប់លេខសម្គាល់បន្ទាត់"</string>
<string name="ColrMmi" msgid="5889782479745764278">"បានភ្ជាប់ការដាក់កម្រិតលេខសម្គាល់បន្ទាត់"</string>
<string name="CfMmi" msgid="8390012691099787178">"បញ្ជូនការហៅបន្ត"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"ហៅទូរសព្ទតាមរយៈ Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ហៅទូរសព្ទតាមរយៈបណ្តាញទូរសព្ទចល័ត"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi តែប៉ុណ្ណោះ"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"ការហៅទូរសព្ទឆ្លងស៊ីមតាមរយៈ <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិនបានបញ្ជូនបន្ត"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> បន្ទាប់ពី <xliff:g id="TIME_DELAY">{2}</xliff:g> វិនាទី"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index b7356e1..9fc9f36 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ಒಳಬರುವ ಕರೆಮಾಡುವವರ ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ಹೊರಹೋಗುವ ಕರೆಮಾಡುವವರ ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ಲೈನ್ ID ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
<string name="ColrMmi" msgid="5889782479745764278">"ಲೈನ್ ID ನಿರ್ಬಂಧನೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
<string name="CfMmi" msgid="8390012691099787178">"ಕರೆಯ ರವಾನೆ"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"ವೈ-ಫೈ ಬಳಸಿ ಕರೆ ಮಾಡಿ"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಬಳಸಿ ಕರೆ ಮಾಡಿ"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"ವೈ-ಫೈ ಮಾತ್ರ"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ಫಾರ್ವರ್ಡ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> ಸೆಕೆಂಡುಗಳ ನಂತರ <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 31837a3..fd81606b 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"발신자 번호"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"내 발신 번호"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"환승편 ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"환승편 ID 제한"</string>
<string name="CfMmi" msgid="8390012691099787178">"착신전환"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi를 통해 통화"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"모바일 네트워크를 통해 통화"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi에서만"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Cross SIM 통화"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: 착신전환 안됨"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g><xliff:g id="TIME_DELAY">{2}</xliff:g>초 후"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 4211bed..612193c 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Кирүүчү номурду аныктоо"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Чыгуучу номурду аныктоо"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Туташкан линия ID-си"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Туташкан линия ID-син Чектөө"</string>
<string name="CfMmi" msgid="8390012691099787178">"Башка номерге багыттоо"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi аркылуу чалуу"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Мобилдик тармак аркылуу чалуу"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi гана"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> SIM карталарынан кайчылаш чалуу"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Багытталган эмес"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секунддан кийин"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 0646254..760d920 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ໝາຍເລກຜູ່ໂທເຂົ້າ"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ໝາຍເລກຜູ່ໂທອອກ"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Line ID ທີ່ເຊື່ອມໂຍງ"</string>
<string name="ColrMmi" msgid="5889782479745764278">"ຂໍ້ຈຳກັດ Line ID ທີ່ເຊື່ອມໂຍງ"</string>
<string name="CfMmi" msgid="8390012691099787178">"ການໂອນສາຍ"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"ໂທຜ່ານ Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ໂທຜ່ານເຄືອຂ່າຍມືຖື"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi ເທົ່ານັ້ນ"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> ການໂທຂ້າມຊິມ"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ບໍ່ຖືກສົ່ງຕໍ່"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> ຫຼັງຈາກ <xliff:g id="TIME_DELAY">{2}</xliff:g> ວິນາທີ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index d83506e..da18b18 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Įeinančio skambintojo ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Išeinančio skambintojo ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Prijungtos eilutės ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Prijungtos eilutės ID apribojimas"</string>
<string name="CfMmi" msgid="8390012691099787178">"Skambučio peradresavimas"</string>
@@ -148,6 +149,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Skambinimas naudojant „Wi-Fi“"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Skambinimas naudojant mobiliojo ryšio tinklą"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Tik „Wi-Fi“"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"„<xliff:g id="SPN">%s</xliff:g>“: skambinimas per SIM korteles"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neperadresuota"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sek."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 68609ce..4fdd570f 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -58,7 +58,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Ienākošā zvana zvanītāja ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Izejošā zvana zvanītāja ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Saistītās līnijas ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Saistītās līnijas ID ierobežojums"</string>
<string name="CfMmi" msgid="8390012691099787178">"Zvanu pāradresācija"</string>
@@ -147,6 +148,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Zvani Wi-Fi tīklā"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Zvani mobilajā tīklā"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Tikai Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g>: zvanīšana, izmantojot dažādas SIM kartes"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nav pāradresēts"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pēc <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundes(-ēm)"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index c41b56c..b18ce23 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID на дојдовен повикувач"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID на појдовен повикувач"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID на поврзана линија"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Забрана на ID на поврзана линија"</string>
<string name="CfMmi" msgid="8390012691099787178">"Проследување повик"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Повикувај преку Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Повикувај преку мобилна мрежа"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Само Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Повици преку повеќе SIM-картички на <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не е препратено"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> по <xliff:g id="TIME_DELAY">{2}</xliff:g> секунди"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 30c0d03..d21ab5a 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ഇൻകമിംഗ് വിളിച്ച നമ്പർ"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ഔട്ട്ഗോയിംഗ് വിളിച്ച നമ്പർ"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"കണക്റ്റുചെയ്തിരിക്കുന്ന ലൈൻ ഐഡി"</string>
<string name="ColrMmi" msgid="5889782479745764278">"കണക്റ്റുചെയ്തിരിക്കുന്ന ലൈൻ ഐഡി നിയന്ത്രണം"</string>
<string name="CfMmi" msgid="8390012691099787178">"കോൾ ഫോർവേഡിംഗ്"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"വൈഫൈ മുഖേനയുള്ള കോൾ"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"മൊബൈൽ നെറ്റ്വർക്ക് മുഖേനയുള്ള കോൾ"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"വൈഫൈ മാത്രം"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> ക്രോസ് സിം കോളിംഗ്"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: കൈമാറിയില്ല"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> നിമിഷത്തിനുശേഷം <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 2966035..778a15b 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -49,15 +49,16 @@
<string name="invalidPuk" msgid="8831151490931907083">"8-с цөөнгүй тооноос бүтэх PUK-г бичнэ үү."</string>
<string name="needPuk" msgid="7321876090152422918">"SIM картны PUK-түгжигдсэн. Тайлах бол PUK кодыг бичнэ үү."</string>
<string name="needPuk2" msgid="7032612093451537186">"SIM картыг блокоос гаргах бол PUK2-г бичнэ үү."</string>
- <string name="enablePin" msgid="2543771964137091212">"Амжилтгүй боллоо, СИМ/РҮИМ түгжээг идэвхжүүлнэ үү."</string>
+ <string name="enablePin" msgid="2543771964137091212">"Амжилтгүй боллоо, SIM/РҮИМ түгжээг идэвхжүүлнэ үү."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
- <item quantity="other">Таны СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER_1">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item>
- <item quantity="one">Таны СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER_0">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item>
+ <item quantity="other">Таны SIM түгжигдэхээс өмнө танд <xliff:g id="NUMBER_1">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item>
+ <item quantity="one">Таны SIM түгжигдэхээс өмнө танд <xliff:g id="NUMBER_0">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item>
</plurals>
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Дуудлага хийгчийн ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Гарч байгаа дуудлага хийгчийн ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Холбогдсон шугамын ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Холбогдсон шугамын ID Хязгаарлалт"</string>
<string name="CfMmi" msgid="8390012691099787178">"Дуудлага дамжуулах"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi-р залгах"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Мобайл сүлжээгээр дуудлага хийх"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Зөвхөн Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> SIM хоорондын дуудлага"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: дамжуулагдаагүй"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> секундын дараа"</string>
@@ -809,7 +813,7 @@
<string name="relationTypeAssistant" msgid="4057605157116589315">"Туслагч"</string>
<string name="relationTypeBrother" msgid="7141662427379247820">"Ах"</string>
<string name="relationTypeChild" msgid="9076258911292693601">"Хүүхэд"</string>
- <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"Дотоод Түнш"</string>
+ <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"Хамтран амьдрагч"</string>
<string name="relationTypeFather" msgid="3856225062864790596">"Эцэг"</string>
<string name="relationTypeFriend" msgid="3192092625893980574">"Найз"</string>
<string name="relationTypeManager" msgid="2272860813153171857">"Менежер"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index b65a316..dc5175b 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"येणारा कॉलर आयडी"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"केला जाणारा कॉलर आयडी"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"कनेक्ट केलेला रेखा आयडी"</string>
<string name="ColrMmi" msgid="5889782479745764278">"कनेक्ट केलेला रेखा आयडी प्रतिबंध"</string>
<string name="CfMmi" msgid="8390012691099787178">"कॉल फॉरवर्डिंग"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"वाय-फायवरून कॉल करा"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"मोबाइल नेटवर्कवरून कॉल करा"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"केवळ वाय-फाय"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अग्रेषित केला नाही"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकंदांनंतर <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -394,9 +399,9 @@
<string name="permlab_writeSettings" msgid="8057285063719277394">"सिस्टम सेटिंग्ज सुधारित करा"</string>
<string name="permdesc_writeSettings" msgid="8293047411196067188">"सिस्टीमचा सेटिंग्ज डेटा सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपल्या सिस्टीमचे कॉंफिगरेशन दूषित करू शकतात."</string>
<string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"सुरूवातीस चालवा"</string>
- <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"जसे सिस्टम बूट करणे समाप्त करते तसे अॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे टॅबलेट प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर टॅबलेटला धीमे करण्यास अॅप ला अनुमती देते."</string>
+ <string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"जसे सिस्टम बूट करणे समाप्त करते तसे अॅप ला स्वतः सुरू करण्यास अनुमती देते. यामुळे टॅबलेट सुरू करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर टॅबलेटला धीमे करण्यास अॅप ला अनुमती देते."</string>
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"सिस्टम बूट होणे संपल्यावर ॲपला स्वतः सुरू होण्याची अनुमती देते. यामुळे तुमच्या Android TV डिव्हाइसला सुरू होण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर डिव्हाइसलाच धीमे करण्याची अनुमती ॲपला देते."</string>
- <string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"जसे सिस्टम बूट करणे समाप्त करते तसे अॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे फोन प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर फोनला धीमे करण्यास अॅप ला अनुमती देते."</string>
+ <string name="permdesc_receiveBootCompleted" product="default" msgid="7912677044558690092">"जसे सिस्टम बूट करणे समाप्त करते तसे अॅप ला स्वतः सुरू करण्यास अनुमती देते. यामुळे फोन सुरू करण्यास वेळ लागू शकतो आणि नेहमी सुरू राहून एकंदर फोनला धीमे करण्यास अॅप ला अनुमती देते."</string>
<string name="permlab_broadcastSticky" msgid="4552241916400572230">"रोचक प्रसारण पाठवा"</string>
<string name="permdesc_broadcastSticky" product="tablet" msgid="5058486069846384013">"रोचक प्रसारणे पाठविण्यासाठी अॅप ला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो टॅब्लेटला धीमा किंवा अस्थिर करू शकतो."</string>
<string name="permdesc_broadcastSticky" product="tv" msgid="2338185920171000650">"चिकट प्रसारणे पाठविण्यासाठी ॲपला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो तुमच्या Android TV डिव्हाइसला धीमा किंवा अस्थिर करू शकतो."</string>
@@ -910,7 +915,7 @@
<string name="keyguard_accessibility_status" msgid="6792745049712397237">"स्थिती"</string>
<string name="keyguard_accessibility_camera" msgid="7862557559464986528">"कॅमेरा"</string>
<string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"मीडिया नियंत्रणे"</string>
- <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"विजेट पुनर्क्रमित करणे प्रारंभ झाले."</string>
+ <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"विजेट पुनर्क्रमित करणे सुरू झाले."</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"विजेट पुनर्क्रमित करणे समाप्त झाले."</string>
<string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"विजेट <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> हटविले."</string>
<string name="keyguard_accessibility_expand_lock_area" msgid="4215280881346033434">"अनलॉक क्षेत्र विस्तृत करा."</string>
@@ -1203,7 +1208,7 @@
<string name="android_upgrading_title" product="tablet" msgid="4268417249079938805">"टॅबलेट अपडेट होत आहे…"</string>
<string name="android_upgrading_title" product="device" msgid="6774767702998149762">"डिव्हाइस अपडेट होत आहे…"</string>
<string name="android_start_title" product="default" msgid="4036708252778757652">"फोन सुरू होत आहे…"</string>
- <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android प्रारंभ करत आहे…"</string>
+ <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android सुरू करत आहे…"</string>
<string name="android_start_title" product="tablet" msgid="4429767260263190344">"टॅबलेट सुरू होत आहे…"</string>
<string name="android_start_title" product="device" msgid="6967413819673299309">"डिव्हाइस सुरू होत आहे…"</string>
<string name="android_upgrading_fstrim" msgid="3259087575528515329">"संचयन ऑप्टिमाइझ करत आहे."</string>
@@ -1211,7 +1216,7 @@
<string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g> श्रेणीसुधारित करत आहे…"</string>
<string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_0">%1$d</xliff:g> अॅप ऑप्टिमाइझ करत आहे."</string>
<string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> तयार करत आहे."</string>
- <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"अॅप्स प्रारंभ करत आहे."</string>
+ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"अॅप्स सुरू करत आहे."</string>
<string name="android_upgrading_complete" msgid="409800058018374746">"बूट समाप्त होत आहे."</string>
<string name="heavy_weight_notification" msgid="8382784283600329576">"रन होणारे <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="heavy_weight_notification_detail" msgid="6802247239468404078">"गेमवर परत जाण्यासाठी टॅप करा"</string>
@@ -1288,7 +1293,7 @@
<string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"नेहमी अनुमती द्या"</string>
<string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"कधीही अनुमती देऊ नका"</string>
<string name="sim_removed_title" msgid="5387212933992546283">"सिम कार्ड काढले"</string>
- <string name="sim_removed_message" msgid="9051174064474904617">"तुम्ही एक वैध सिम कार्ड घालून प्रारंभ करेपर्यंत मोबाइल नेटवर्क अनुपलब्ध असेल."</string>
+ <string name="sim_removed_message" msgid="9051174064474904617">"तुम्ही एक वैध सिम कार्ड घालून सुरू करेपर्यंत मोबाइल नेटवर्क अनुपलब्ध असेल."</string>
<string name="sim_done_button" msgid="6464250841528410598">"पूर्ण झाले"</string>
<string name="sim_added_title" msgid="7930779986759414595">"सिम कार्ड जोडले"</string>
<string name="sim_added_message" msgid="6602906609509958680">"मोबाइल नेटवर्कवर अॅक्सेस करण्यासाठी तुमचे डिव्हाइस रीस्टार्ट करा."</string>
@@ -1917,7 +1922,7 @@
<string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> ला अनपिन करा"</string>
<string name="app_info" msgid="6113278084877079851">"अॅप माहिती"</string>
<string name="negative_duration" msgid="1938335096972945232">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="demo_starting_message" msgid="6577581216125805905">"डेमो प्रारंभ करत आहे..."</string>
+ <string name="demo_starting_message" msgid="6577581216125805905">"डेमो सुरू करत आहे..."</string>
<string name="demo_restarting_message" msgid="1160053183701746766">"डिव्हाइस रीसेट करत आहे..."</string>
<string name="suspended_widget_accessibility" msgid="6331451091851326101">"<xliff:g id="LABEL">%1$s</xliff:g> अक्षम केले"</string>
<string name="conference_call" msgid="5731633152336490471">"कॉंफरन्स कॉल"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index f45f32e..a14ea62 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID Pemanggil Masuk"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID Pemanggil Keluar"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID Laluan yang disambungkan"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Sekatan ID Laluan yang disambungkan"</string>
<string name="CfMmi" msgid="8390012691099787178">"Pemajuan panggilan"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Panggil melalui Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Panggil melalui rangkaian mudah alih"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi sahaja"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Tidak dimajukan"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> selepas <xliff:g id="TIME_DELAY">{2}</xliff:g> saat"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 0cc4d8e..f768d17 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEIDနံပါတ်"</string>
<string name="ClipMmi" msgid="4110549342447630629">"အဝင်ခေါ်ဆိုမှုID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"အထွက်ခေါ်ဆိုခြင်းအိုင်ဒီ"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"လိုင်း ID ချိတ်ဆက်သည်"</string>
<string name="ColrMmi" msgid="5889782479745764278">"လိုင်း ID ချိတ်ဆက်မှု ကန့်သတ်ချက်များ"</string>
<string name="CfMmi" msgid="8390012691099787178">"အဝင်ခေါ်ဆိုမှုအား ထပ်ဆင့်ပို့ခြင်း"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi သုံး၍ ခေါ်ဆိုသည်"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"မိုဘိုင်းကွန်ရက်သုံး၍ ခေါ်ဆိုသည်"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"ကြိုးမဲ့အင်တာနက် သာလျှင်"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Cross-SIM ခေါ်ဆိုမှု"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ထပ်ဆင့်မပို့နိုင်ပါ"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> နောက် <xliff:g id="TIME_DELAY">{2}</xliff:g> စက္ကန့်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 601c6fb..c6831a8 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Inngående nummervisning"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Utgående nummervisning"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Tilkoblet linje-ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Begrensning for tilkoblet linje-ID"</string>
<string name="CfMmi" msgid="8390012691099787178">"Viderekobling"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Ring via Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Ring over mobilnettverk"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Bare Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Ringing mellom SIM-kort med <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Ikke viderekoblet"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> etter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index e53a519..ff0b00e 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"आगमन कलर ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"बाहिरिने कलर ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"लाइन ID जोडियो"</string>
<string name="ColrMmi" msgid="5889782479745764278">"जोडिएको लाइन ID प्रतिबन्ध"</string>
<string name="CfMmi" msgid="8390012691099787178">"कल अगाडि बढाउँदै"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi मार्फत कल गर्नुहोस्"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"मोबाइल नेटवर्कमार्फत कल गर्नुहोस्"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi मात्र"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> क्रस SIM कलिङ"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: अगाडि पठाइएको छैन"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> पछि <xliff:g id="TIME_DELAY">{2}</xliff:g> सेकेन्ड"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 37eb025..4ada7a2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Inkomende beller-ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Uitgaande beller-ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID van verbonden lijn"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Beperking voor ID van verbonden lijn"</string>
<string name="CfMmi" msgid="8390012691099787178">"Gesprek doorschakelen"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Bellen via wifi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Bellen via mobiel netwerk"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Alleen wifi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Cross-sim-bellen van <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: niet doorgeschakeld"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> na <xliff:g id="TIME_DELAY">{2}</xliff:g> seconden"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 2124d49..54e064d 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ଇନକମିଙ୍ଗ କଲର୍ ଆଇଡି"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ଆଉଟଗୋଇଙ୍ଗ୍ କଲର୍ ଆଇଡି"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ସଂଯୁକ୍ତ ଲାଇନ୍ ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"ସଂଯୁକ୍ତ ଲାଇନ୍ ID କଟକଣା"</string>
<string name="CfMmi" msgid="8390012691099787178">"କଲ୍ ଫରୱାର୍ଡିଂ"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"ୱାଇ-ଫାଇ ମାଧ୍ୟମରେ କଲ୍ କରନ୍ତୁ"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ମୋବାଇଲ ନେଟ୍ୱର୍କ ମାଧ୍ୟମରେ କଲ୍ କରନ୍ତୁ"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"କେବଳ ୱାଇ-ଫାଇ"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ଫରୱାର୍ଡ କରାଯାଇନାହିଁ"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ସେକେଣ୍ଡ ପରେ"</string>
@@ -1124,9 +1129,9 @@
<string name="app_running_notification_title" msgid="8985999749231486569">"<xliff:g id="APP_NAME">%1$s</xliff:g> ଚାଲୁଛି"</string>
<string name="app_running_notification_text" msgid="5120815883400228566">"ଅଧିକ ସୂଚନା ପାଇଁ କିମ୍ବା ଆପ୍ ବନ୍ଦ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
<string name="ok" msgid="2646370155170753815">"ଠିକ୍ ଅଛି"</string>
- <string name="cancel" msgid="6908697720451760115">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="cancel" msgid="6908697720451760115">"ବାତିଲ୍ କରନ୍ତୁ"</string>
<string name="yes" msgid="9069828999585032361">"ଠିକ୍ ଅଛି"</string>
- <string name="no" msgid="5122037903299899715">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="no" msgid="5122037903299899715">"ବାତିଲ୍ କରନ୍ତୁ"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"ଧ୍ୟାନଦିଅନ୍ତୁ"</string>
<string name="loading" msgid="3138021523725055037">"ଲୋଡ୍ କରାଯାଉଛି…"</string>
<string name="capital_on" msgid="2770685323900821829">"ଚାଲୁ"</string>
@@ -1282,7 +1287,7 @@
<string name="sms_short_code_details" msgid="2723725738333388351">"ଏହା ଦ୍ୱାରା "<b>" ଆପଣଙ୍କ ମୋବାଇଲ୍ ଆକାଉଣ୍ଟରୁ ପଇସା କଟିପାରେ। "</b></string>
<string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>" ଆପଣଙ୍କ ମୋବାଇଲ୍ ଆକାଉଣ୍ଟରୁ ପଇସା କଟିପାରେ। "</b></string>
<string name="sms_short_code_confirm_allow" msgid="920477594325526691">"ପଠାନ୍ତୁ"</string>
- <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"ବାତିଲ୍ କରନ୍ତୁ"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"ମୋ ପସନ୍ଦ ମନେରଖନ୍ତୁ"</string>
<string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"ଏହାକୁ ଆପଣ ସେଟିଙ୍ଗ ଓ ଆପ୍ରେ ପରବର୍ତ୍ତୀ ସମୟରେ ବଦଳାଇପାରିବେ"</string>
<string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"ସର୍ବଦା ଅନୁମତି ଦିଅନ୍ତୁ"</string>
@@ -1500,7 +1505,7 @@
<string name="date_picker_prev_month_button" msgid="3418694374017868369">"ପୂର୍ବ ମାସ"</string>
<string name="date_picker_next_month_button" msgid="4858207337779144840">"ପରବର୍ତ୍ତୀ ମାସ"</string>
<string name="keyboardview_keycode_alt" msgid="8997420058584292385">"ALT"</string>
- <string name="keyboardview_keycode_cancel" msgid="2134624484115716975">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="keyboardview_keycode_cancel" msgid="2134624484115716975">"ବାତିଲ୍ କରନ୍ତୁ"</string>
<string name="keyboardview_keycode_delete" msgid="2661117313730098650">"ଡିଲିଟ୍ କରନ୍ତୁ"</string>
<string name="keyboardview_keycode_done" msgid="2524518019001653851">"ହୋଇଗଲା"</string>
<string name="keyboardview_keycode_mode_change" msgid="2743735349997999020">"ମୋଡ୍ ପରିବର୍ତ୍ତନ"</string>
@@ -1761,7 +1766,7 @@
<string name="mediasize_japanese_you4" msgid="5552111912684384833">"You4"</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>
+ <string name="write_fail_reason_cancelled" msgid="2344081488493969190">"ବାତିଲ୍ କରାଗଲା"</string>
<string name="write_fail_reason_cannot_write" msgid="432118118378451508">"କଣ୍ଟେଣ୍ଟ ଲେଖିବାବେଳେ ତ୍ରୁଟି"</string>
<string name="reason_unknown" msgid="5599739807581133337">"ଅଜଣା"</string>
<string name="reason_service_unavailable" msgid="5288405248063804713">"ପ୍ରିଣ୍ଟ ସେବାକୁ ସକ୍ଷମ କରାଯାଇନାହିଁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 4518a3b..804b77d 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ਇਨਕਮਿੰਗ ਕਾਲਰ ਆਈ.ਡੀ."</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ਆਊਟਗੋਇੰਗ ਕਾਲਰ ਆਈ.ਡੀ."</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ਕਨੈਕਟ ਕੀਤੀ ਲਾਈਨ ਆਈ.ਡੀ."</string>
<string name="ColrMmi" msgid="5889782479745764278">"ਕਨੈਕਟ ਕੀਤੀ ਲਾਈਨ ਆਈ.ਡੀ. ਪ੍ਰਤਿਬੰਧ"</string>
<string name="CfMmi" msgid="8390012691099787178">"ਕਾਲ ਫਾਰਵਰਡਿੰਗ"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"ਵਾਈ-ਫਾਈ \'ਤੇ ਕਾਲ ਕਰੋ"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਤੋਂ ਕਾਲ ਕਰੋ"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"ਸਿਰਫ਼ ਵਾਈ-ਫਾਈ"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ਅੱਗੇ ਨਹੀਂ ਭੇਜਿਆ ਗਿਆ"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> ਸਕਿੰਟਾਂ ਬਾਅਦ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index cfcc2d5..8d669c4 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID rozmówcy przy połączeniach przychodzących"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID rozmówcy przy połączeniach wychodzących"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Identyfikator połączonej linii"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Ograniczenie identyfikatora połączonej linii"</string>
<string name="CfMmi" msgid="8390012691099787178">"Przekierowanie połączeń"</string>
@@ -148,6 +149,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Rozmowa przez Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Połączenia przez sieć komórkową"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Tylko Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Połączenia przez różne karty SIM z <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: nieprzekierowane"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> sekundach"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index e4092fd..9837b88 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Identificador de chamadas recebidas"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Identificador de chamadas realizadas"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID de linha conectada"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restrição de ID de linha conectada"</string>
<string name="CfMmi" msgid="8390012691099787178">"Encaminhamento de chamada"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Chamar via Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Chamar via rede móvel"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Somente Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Chamadas entre chips da <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index d5c3c02..ef7ee98 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID do Autor da Chamada"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID do autor da chamada efetuada"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID de linha ligada"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restrição de ID de linha ligada"</string>
<string name="CfMmi" msgid="8390012691099787178">"Encaminhamento de chamadas"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Chamada por Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Chamada por rede móvel"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Apenas Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Chamadas com vários cartões SIM"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não reencaminhado"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index e4092fd..9837b88 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Identificador de chamadas recebidas"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Identificador de chamadas realizadas"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID de linha conectada"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restrição de ID de linha conectada"</string>
<string name="CfMmi" msgid="8390012691099787178">"Encaminhamento de chamada"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Chamar via Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Chamar via rede móvel"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Somente Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Chamadas entre chips da <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Não encaminhado"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> após <xliff:g id="TIME_DELAY">{2}</xliff:g> segundos"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index b2d2d24..68dad1c 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -58,7 +58,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID apelant de primire"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID apelant"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID-ul liniei conectate"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Restricționarea ID-ului liniei conectate"</string>
<string name="CfMmi" msgid="8390012691099787178">"Redirecționarea apelurilor"</string>
@@ -147,6 +148,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Apelați prin Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Apelați prin rețeaua mobilă"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Numai Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Apelare pe mai multe carduri SIM <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: neredirecționată"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> după <xliff:g id="TIME_DELAY">{2}</xliff:g> secunde"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a4d249a..03383f9 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Идентификация вызывающего абонента"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Идентификация звонящего абонента"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Идентификатор подключенной линии"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Ограничение идентификатора подключенной линии"</string>
<string name="CfMmi" msgid="8390012691099787178">"Переадресация вызовов"</string>
@@ -148,6 +149,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Звонить по Wi‑Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Звонить по мобильной сети"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Только Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Перекрестная работа SIM-карт от \"<xliff:g id="SPN">%s</xliff:g>\""</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не переадресовано"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> через <xliff:g id="TIME_DELAY">{2}</xliff:g> с."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 4277a0d..cfa9bf1 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"පැමිණෙන අමතන්නාගේ ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"පිටතට යන අමතන්නාගේ ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"සම්බන්ධ කළ Line ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"සම්බන්ධ කළ Line ID සීමා කිරීම්"</string>
<string name="CfMmi" msgid="8390012691099787178">"ඇමතුම ඉදිරියට යැවීම"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi ඔස්සේ ඇමතුම"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"ජංගම ජාලය ඔස්සේ ඇමතුම"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi පමණයි"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> හරස් SIM ඇමතුම"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ඉදිරියට නොයවන ලදි"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: තත්පර <xliff:g id="TIME_DELAY">{2}</xliff:g> ට පසුව <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 5f6d557..f8dfc26 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Prichádzajúca identifikácia volajúceho"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Odchádzajúca identifikácia volajúceho"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID pripojenej linky"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Obmedzenie ID pripojenej linky"</string>
<string name="CfMmi" msgid="8390012691099787178">"Presmerovanie hovorov"</string>
@@ -148,6 +149,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Volanie cez Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Volanie cez mobilnú sieť"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Len Wi‑Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Volanie naprieč SIM kartami"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nepresmerované"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po <xliff:g id="TIME_DELAY">{2}</xliff:g> s"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0d77c61..4a5c5da 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID dohodnega klicatelja"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID odhodnega klicatelja"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID povezane linije"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Omejitev ID-ja povezane linije"</string>
<string name="CfMmi" msgid="8390012691099787178">"Preusmerjanje klicev"</string>
@@ -148,6 +149,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Klic prek omrežja Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Klic prek mobilnega omrežja"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Samo Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Klicanje ne glede na kartico SIM operaterja <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ni posredovano"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> po toliko sekundah: <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 218412b..5ee9031 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ID-ja e telefonuesit hyrës"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID-ja e telefonuesit në dalje"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID-ja e linjës së lidhur"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Kufizimi i ID-së së linjës së lidhur"</string>
<string name="CfMmi" msgid="8390012691099787178">"Transferimi i telefonatave"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Telefono nëpërmjet Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Telefono nëpërmjet rrjetit celular"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Vetëm Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nuk u transferua"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pas <xliff:g id="TIME_DELAY">{2}</xliff:g> sekondash"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index e944e8b..a430d56 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -58,7 +58,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Долазни ИД позиваоца"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Одлазни ИД позиваоца"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ИД повезане линије"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Ограничење ИД-а повезане линије"</string>
<string name="CfMmi" msgid="8390012691099787178">"Преусмеравање позива"</string>
@@ -147,6 +148,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Позивање преко WiFi-а"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Позив преко мобилне мреже"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Само WiFi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Позиви са више SIM картица за оператера <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> након <xliff:g id="TIME_DELAY">{2}</xliff:g> секунде/и"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2acc051..186a78a 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI-kod"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Nummerpresentatör för inkommande samtal"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Nummerpresentatör för utgående samtal"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Visning av uppkopplat nummer"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Blockera visning av uppkopplat nummer"</string>
<string name="CfMmi" msgid="8390012691099787178">"Vidarekoppla samtal"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Ring via Wi-Fi"</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>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> – samtal mellan SIM-kort"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Vidarebefordras inte"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g><xliff:g id="DIALING_NUMBER">{1}</xliff:g> efter <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunder"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 079d71c..cf9496d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Kitambulisho cha Mpigaji wa Simu Inayoingia"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"ID ya Mpigaji simu Inayotoka nje"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Kitambulisho cha Mstari Uliounganishwa"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Kizuizi cha Kitambulisho cha Mstari Uliounganishwa"</string>
<string name="CfMmi" msgid="8390012691099787178">"Kusambaza simu"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Piga simu ukitumia WI-FI"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Piga ukitumia mtandao wa simu"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi pekee"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Kipengele cha Kupiga Simu Kupitia SIM Tofauti"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Haijatumiwa mwingine"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> baada ya sekunde <xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index ec9c0a7..f3e5f91 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"உள்வரும் அழைப்பாளர் ஐடி"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"வெளிசெல்லும் அழைப்பாளர் ஐடி"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"இணைக்கப்பட்ட லைன் ஐடி"</string>
<string name="ColrMmi" msgid="5889782479745764278">"இணைக்கப்பட்ட லைன் ஐடியை வரம்பிடல்"</string>
<string name="CfMmi" msgid="8390012691099787178">"அழைப்பு திருப்பிவிடுதல்"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"வைஃபை மூலம் அழை"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"மொபைல் நெட்வொர்க் மூலமாக அழை"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"வைஃபை மட்டும்"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> கிராஸ்-சிம் அழைப்பு"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: பகிரப்படவில்லை"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> வினாடிகளுக்குப் பிறகு <xliff:g id="DIALING_NUMBER">{1}</xliff:g> ஐப் பகிர்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 6483db1..2687aa1 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ఇన్కమింగ్ కాలర్ ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"అవుట్గోయింగ్ కాలర్ ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"కనెక్ట్ చేయబడిన పంక్తి ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"కనెక్ట్ చేయబడిన పంక్తి ID నియంత్రణ"</string>
<string name="CfMmi" msgid="8390012691099787178">"కాల్ ఫార్వర్డింగ్"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi ద్వారా కాల్"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"మొబైల్ నెట్వర్క్ ద్వారా కాల్"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi మాత్రమే"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> క్రాస్-SIM కాలింగ్"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ఫార్వార్డ్ చేయబడలేదు"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> సెకన్ల తర్వాత <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 094b6c8..01ffd62 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"หมายเลขผู้โทรเข้า"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"หมายเลขผู้โทรออก"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"รหัสสายที่เชื่อมต่อ"</string>
<string name="ColrMmi" msgid="5889782479745764278">"ข้อจำกัดรหัสสายที่เชื่อมต่อ"</string>
<string name="CfMmi" msgid="8390012691099787178">"การโอนสาย"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"โทรผ่าน Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"โทรผ่านเครือข่ายมือถือ"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi เท่านั้น"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"การโทรข้ามซิม <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> หลังผ่านไป <xliff:g id="TIME_DELAY">{2}</xliff:g> วินาที"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 09ace93..40968eb 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Papasok na Caller ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Papalabas na Caller ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Connected Line ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Paghihigpit sa Connected Line ID"</string>
<string name="CfMmi" msgid="8390012691099787178">"Pagpapasa ng tawag"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Tumawag gamit ang Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Tumawag gamit ang mobile network"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Wi-Fi lang"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"Cross-SIM na Pagtawag sa <xliff:g id="SPN">%s</xliff:g>"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Hindi naipasa"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> pagkatapos ng <xliff:g id="TIME_DELAY">{2}</xliff:g> (na) segundo"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index af10694..342ff20 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Gelen Çağrı Kimliği"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Giden Çağrı Kimliği"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Bağlanılan Hat Kimliği"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Bağlanılan Hat Kimliğini Kısıtlama"</string>
<string name="CfMmi" msgid="8390012691099787178">"Çağrı yönlendirme"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Kablosuz ağ üzerinden arama"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Mobil ağ üzerinden arama"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Yalnızca kablosuz"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Çapraz SIM Araması"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yönlendirilmedi"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="TIME_DELAY">{2}</xliff:g> saniye sonra <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f264fbb..cf2c6f1 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -59,7 +59,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Вхідн. ід. абонента"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Вихід. ід. абонента"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Ідентифікатор під’єднаної лінії"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Обмеження ідентифікатора під’єднаної лінії"</string>
<string name="CfMmi" msgid="8390012691099787178">"Переадресація виклику"</string>
@@ -148,6 +149,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Телефонувати через Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Телефонувати через мобільну мережу"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Лише Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> – виклики між SIM-картами"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: не переслано"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> після <xliff:g id="TIME_DELAY">{2}</xliff:g> сек."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 37cb12a..8f54c27 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"ان کمنگ کالر ID"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"آؤٹ گوئنگ کالر ID"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"منسلک لائن ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"منسلک لائن ID کی پابندی"</string>
<string name="CfMmi" msgid="8390012691099787178">"کال فارورڈنگ"</string>
@@ -146,6 +147,10 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi پر کال کریں"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"موبائل نیٹ ورک پر کال کریں"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"صرف Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <!-- no translation found for crossSimFormat_spn_cross_sim_calling (779976494687695991) -->
+ <skip />
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : فارورڈ نہیں کی گئی"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> بعد از <xliff:g id="TIME_DELAY">{2}</xliff:g> سیکنڈ"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 23fd462..a8bc4ba 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Kiruvchi raqami"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Chiquvchi raqami"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"Qo‘ng‘iroq qiluvchining raqami"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Qo‘ng‘iroq qiluvchining raqamini cheklash"</string>
<string name="CfMmi" msgid="8390012691099787178">"Chaqiruvlarni uzatish"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Wi-Fi orqali chaqiruv"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Mobil tarmoq orqali chaqiruv"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Faqat Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Umumiy sim chaqiruvlar"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Yo‘naltirilmadi"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> <xliff:g id="TIME_DELAY">{2}</xliff:g> soniyadan so‘ng"</string>
@@ -1278,15 +1282,15 @@
<string name="sms_control_message" msgid="6574313876316388239">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> katta miqdordagi SMS xabarlarini jo‘natmoqda. Ushbu ilovaga xabarlar jo‘natishni davom ettirishga ruxsat berasizmi?"</string>
<string name="sms_control_yes" msgid="4858845109269524622">"Ruxsat berish"</string>
<string name="sms_control_no" msgid="4845717880040355570">"Rad etish"</string>
- <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b>ga xabar jo‘natishni xohlaydi."</string>
- <string name="sms_short_code_details" msgid="2723725738333388351">"Bunda, mobil hisobingizdan "<b>"to‘lov olinishi mumkin"</b>"."</string>
- <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Bunda, mobil hisobingizdan to‘lov olinishi mumkin."</b></string>
+ <string name="sms_short_code_confirm_message" msgid="1385416688897538724">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ilovasi <b><xliff:g id="DEST_ADDRESS">%2$s</xliff:g></b> raqamiga xabar yubormoqchi."</string>
+ <string name="sms_short_code_details" msgid="2723725738333388351">"Mobil aloqa hisobingizdan "<b>"pul olinishi mumkin"</b>"."</string>
+ <string name="sms_premium_short_code_details" msgid="1400296309866638111"><b>"Mobil aloqa hisobingizdan pul olinishi mumkin."</b></string>
<string name="sms_short_code_confirm_allow" msgid="920477594325526691">"Yuborish"</string>
<string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Bekor qilish"</string>
<string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Tanlovim eslab qolinsin"</string>
- <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"Siz buni keyinroq sozlamalar > ilovalar menusidan o‘zgartirishingiz mumkin"</string>
- <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"Doimo ruxsat berilsin"</string>
- <string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"Hech qachon ruxsat berilmasin"</string>
+ <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"Buni keyinroq Sozlamalar > Ilovalar menyusidan o‘zgartirishingiz mumkin"</string>
+ <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"Doim ruxsat"</string>
+ <string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"Ruxsat berilmasin"</string>
<string name="sim_removed_title" msgid="5387212933992546283">"SIM karta olib tashlandi"</string>
<string name="sim_removed_message" msgid="9051174064474904617">"Ishlaydigan SIM kartani qo‘yib, qurilmangizni qaytadan ishga tushirmasangiz, mobayl tarmoq mavjud bo‘lmaydi."</string>
<string name="sim_done_button" msgid="6464250841528410598">"Tayyor"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index bfc509a..0af241e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"Số gọi đến"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"Số gọi đi"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"ID đường kết nối"</string>
<string name="ColrMmi" msgid="5889782479745764278">"Giới hạn ID đường kết nối"</string>
<string name="CfMmi" msgid="8390012691099787178">"Chuyển tiếp cuộc gọi"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Gọi qua Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Gọi qua mạng di động"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"Chỉ Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> Gọi bằng nhiều SIM"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Không được chuyển tiếp"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> sau <xliff:g id="TIME_DELAY">{2}</xliff:g> giây"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 85a7dae..4503305 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"来电显示"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"本机号码"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"连接的线路ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"连接的线路ID限制"</string>
<string name="CfMmi" msgid="8390012691099787178">"来电转接"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"通过 WLAN 进行通话"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"通过移动网络进行通话"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"仅限 WLAN"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> 跨 SIM 卡通话"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:无法转接"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g>秒后<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 6d06e68..92b007c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"來電顯示"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"本機號碼"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"連接線識別功能"</string>
<string name="ColrMmi" msgid="5889782479745764278">"連接線識別限制"</string>
<string name="CfMmi" msgid="8390012691099787178">"來電轉駁"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"使用 Wi-Fi 通話"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"使用流動網絡通話"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"只限 Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g> 跨 SIM 卡通話"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:尚未轉接"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> 於 <xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後轉接"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5ba35c7..df2d5ea 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"來電顯示"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"本機號碼"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"連接的線路 ID"</string>
<string name="ColrMmi" msgid="5889782479745764278">"連接的線路 ID 限制"</string>
<string name="CfMmi" msgid="8390012691099787178">"來電轉接"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"透過 Wi-Fi 進行通話"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"透過行動網路進行通話"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"只限 Wi-Fi"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"「<xliff:g id="SPN">%s</xliff:g>」跨 SIM 卡通話"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:未轉接"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:<xliff:g id="TIME_DELAY">{2}</xliff:g> 秒後 <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index b391b4d..3f2d547 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -57,7 +57,8 @@
<string name="imei" msgid="2157082351232630390">"IMEI"</string>
<string name="meid" msgid="3291227361605924674">"MEID"</string>
<string name="ClipMmi" msgid="4110549342447630629">"I-ID Yocingo Olungenayo"</string>
- <string name="ClirMmi" msgid="4702929460236547156">"I-ID Yomshayeli Ephumayo"</string>
+ <!-- no translation found for ClirMmi (6752346475055446417) -->
+ <skip />
<string name="ColpMmi" msgid="4736462893284419302">"I-ID yomugqa exhumekile"</string>
<string name="ColrMmi" msgid="5889782479745764278">"I-ID yomugqa oxhumekile ikhawulelwe"</string>
<string name="CfMmi" msgid="8390012691099787178">"Ukudlulisa ikholi"</string>
@@ -146,6 +147,9 @@
<string name="wfc_mode_wifi_preferred_summary" msgid="1035175836270943089">"Ikholi esebenza nge-Wi-Fi"</string>
<string name="wfc_mode_cellular_preferred_summary" msgid="4958965609212575619">"Shaya ngenethiwekhi yeselula"</string>
<string name="wfc_mode_wifi_only_summary" msgid="104951993894678665">"I-Wi-Fi kuphela"</string>
+ <!-- no translation found for crossSimFormat_spn (9125246077491634262) -->
+ <skip />
+ <string name="crossSimFormat_spn_cross_sim_calling" msgid="779976494687695991">"<xliff:g id="SPN">%s</xliff:g>Ukwenza ikholi kwe-Cross Sim"</string>
<string name="cfTemplateNotForwarded" msgid="862202427794270501">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Akudlulisiwe"</string>
<string name="cfTemplateForwarded" msgid="9132506315842157860">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
<string name="cfTemplateForwardedTime" msgid="735042369233323609">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> emuva kwamasekhondi angu-<xliff:g id="TIME_DELAY">{2}</xliff:g>"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ef54db1a..be7ecfc 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -9013,6 +9013,11 @@
changed at runtime by calling
{@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)}. -->
<attr name="tunerCount" format="integer" />
+ <!-- Attribute whether the TV input service can pause recording programs.
+ This value can be changed at runtime by calling
+ {@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)}
+ . -->
+ <attr name="canPauseRecording" format="boolean" />
</declare-styleable>
<!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 060c8b1..0185714 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2494,7 +2494,11 @@
<code>grant-uri-permission</code> tag, a child of the
{@link #AndroidManifestProvider provider} tag, describing a specific
URI path that can be granted as a permission. This tag can be
- specified multiple time to supply multiple paths. -->
+ specified multiple time to supply multiple paths. If multiple
+ path matching attributes are supplied, they will be evaluated in the
+ following order with the first attribute being the only one honored:
+ <code>pathAdvancedPattern</code>, <code>pathPattern</code>,
+ <code>pathPrefix</code>, <code>pathSuffix</code>, <code>path</code>. -->
<declare-styleable name="AndroidManifestGrantUriPermission" parent="AndroidManifestProvider">
<!-- Specify a URI path that must exactly match, as per
{@link android.os.PatternMatcher} with
@@ -2514,18 +2518,37 @@
"\\\\". This is basically the same as what you would need to
write if constructing the string in Java code. -->
<attr name="pathPattern" format="string" />
+ <!-- Specify a URI path that matches an advanced pattern, as per
+ {@link android.os.PatternMatcher} with
+ {@link android.os.PatternMatcher#PATTERN_ADVANCED_GLOB}.
+ Note that because '\' is used as an escape character when
+ reading the string from XML (before it is parsed as a pattern),
+ you will need to double-escape: for example a literal "*" would
+ be written as "\\*" and a literal "\" would be written as
+ "\\\\". This is basically the same as what you would need to
+ write if constructing the string in Java code. -->
+ <attr name="pathAdvancedPattern" format="string"/>
+ <!-- Specify a URI path that must be a suffix to match, as per
+ {@link android.os.PatternMatcher} with
+ {@link android.os.PatternMatcher#PATTERN_SUFFIX}. -->
+ <attr name="pathSuffix" format="string" />
</declare-styleable>
<!-- Attributes that can be supplied in an AndroidManifest.xml
<code>path-permission</code> tag, a child of the
{@link #AndroidManifestProvider provider} tag, describing a permission
that allows access to a specific path in the provider. This tag can be
- specified multiple time to supply multiple paths. -->
+ specified multiple time to supply multiple paths. If multiple
+ path matching attributes are supplied, they will be evaluated in the
+ following order with the first attribute being the only one honored:
+ <code>pathAdvancedPattern</code>, <code>pathPattern</code>,
+ <code>pathPrefix</code>, <code>pathSuffix</code>, <code>path</code>.-->
<declare-styleable name="AndroidManifestPathPermission" parent="AndroidManifestProvider">
<attr name="path" />
<attr name="pathPrefix" />
<attr name="pathPattern" />
<attr name="pathAdvancedPattern" format="string"/>
+ <attr name="pathSuffix" />
<attr name="permission" />
<attr name="readPermission" />
<attr name="writePermission" />
@@ -2977,6 +3000,22 @@
"\\\\". This is basically the same as what you would need to
write if constructing the string in Java code. -->
<attr name="sspPattern" format="string" />
+ <!-- Specify a URI scheme specific part that matches an advanced pattern, as per
+ {@link android.content.IntentFilter#addDataSchemeSpecificPart
+ IntentFilter.addDataSchemeSpecificPart()} with
+ {@link android.os.PatternMatcher#PATTERN_ADVANCED_GLOB}.
+ Note that because '\' is used as an escape character when
+ reading the string from XML (before it is parsed as a pattern),
+ you will need to double-escape: for example a literal "*" would
+ be written as "\\*" and a literal "\" would be written as
+ "\\\\". This is basically the same as what you would need to
+ write if constructing the string in Java code. -->
+ <attr name="sspAdvancedPattern" format="string" />
+ <!-- Specify a URI scheme specific part that must be a suffix to match, as per
+ {@link android.content.IntentFilter#addDataSchemeSpecificPart
+ IntentFilter.addDataSchemeSpecificPart()} with
+ {@link android.os.PatternMatcher#PATTERN_SUFFIX}. -->
+ <attr name="sspSuffix" format="string" />
<!-- Specify a URI authority host that is handled, as per
{@link android.content.IntentFilter#addDataAuthority
IntentFilter.addDataAuthority()}.
@@ -3021,6 +3060,11 @@
"\\\\". This is basically the same as what you would need to
write if constructing the string in Java code. -->
<attr name="pathAdvancedPattern" />
+ <!-- Specify a URI path that must be a suffix to match, as per
+ {@link android.content.IntentFilter#addDataPath
+ IntentFilter.addDataPath()} with
+ {@link android.os.PatternMatcher#PATTERN_SUFFIX}. -->
+ <attr name="pathSuffix" />
</declare-styleable>
<!-- Attributes that can be supplied in an AndroidManifest.xml
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 110e77a..8940776 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -234,4 +234,78 @@
<color name="personal_apps_suspension_notification_color">#1A73E8</color>
<color name="conversation_important_highlight">#F9AB00</color>
+
+ <!-- Lightest shade of the main color used by the system. White.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_0">#ffffff</color>
+ <!-- Shade of the main system color at 95% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_50">#ebf1f8</color>
+ <!-- Shade of the main system color at 90% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_100">#dde3ea</color>
+ <!-- Shade of the main system color at 80% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_200">#c1c7cd</color>
+ <!-- Shade of the main system color at 70% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_300">#a6acb2</color>
+ <!-- Shade of the main system color at 60% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_400">#8b9197</color>
+ <!-- Shade of the main system color at 50% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_500">#72787d</color>
+ <!-- Shade of the main system color at 40% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_600">#595f64</color>
+ <!-- Shade of the main system color at 30% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_700">#42474d</color>
+ <!-- Shade of the main system color at 20% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_800">#2c3136</color>
+ <!-- Shade of the main system color at 10% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_900">#171c21</color>
+ <!-- Darkest shade of the main color used by the system. Black.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_main_1000">#000000</color>
+
+ <!-- Lightest shade of the accent color used by the system. White.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_0">#ffffff</color>
+ <!-- Shade of the accent system color at 95% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_50">#91fff4</color>
+ <!-- Shade of the accent system color at 90% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_100">#83f6e5</color>
+ <!-- Shade of the accent system color at 80% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_200">#65d9c9</color>
+ <!-- Shade of the accent system color at 70% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_300">#45bdae</color>
+ <!-- Shade of the accent system color at 60% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_400">#1fa293</color>
+ <!-- Shade of the accent system color at 50% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_500">#00877a</color>
+ <!-- Shade of the accent system color at 40% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_600">#006d61</color>
+ <!-- Shade of the accent system color at 30% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_700">#005449</color>
+ <!-- Shade of the accent system color at 20% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_800">#003c33</color>
+ <!-- Shade of the accent system color at 10% lightness.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_900">#00271e</color>
+ <!-- Darkest shade of the accent color used by the system. Black.
+ This value can be overlaid at runtime by OverlayManager RROs. -->
+ <color name="system_accent_1000">#000000</color>
</resources>
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 310ca89..b558087 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -33,14 +33,14 @@
<color name="tertiary_device_default_settings">@color/tertiary_material_settings</color>
<color name="quaternary_device_default_settings">@color/quaternary_material_settings</color>
- <color name="accent_device_default_light">@color/accent_material_light</color>
- <color name="accent_device_default_dark">@color/accent_material_dark</color>
+ <color name="accent_device_default_light">@color/system_accent_500</color>
+ <color name="accent_device_default_dark">@color/system_accent_200</color>
<color name="accent_device_default">@color/accent_device_default_light</color>
- <color name="background_device_default_dark">#1A1A1A</color>
- <color name="background_device_default_light">#F2F2F2</color>
- <color name="background_floating_device_default_dark">#0D0D0D</color>
- <color name="background_floating_device_default_light">#CCCCCC</color>
+ <color name="background_device_default_dark">@color/system_main_900</color>
+ <color name="background_device_default_light">@color/system_main_100</color>
+ <color name="background_floating_device_default_dark">@color/system_main_800</color>
+ <color name="background_floating_device_default_light">@color/system_main_200</color>
<!-- Error color -->
<color name="error_color_device_default_dark">@color/error_color_material_dark</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 487847a..529db3f5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -58,6 +58,7 @@
<item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
+ <item><xliff:g id="id">@string/status_bar_no_calling</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
<item><xliff:g id="id">@string/status_bar_sensors_off</xliff:g></item>
</string-array>
@@ -94,6 +95,7 @@
<string translatable="false" name="status_bar_microphone">microphone</string>
<string translatable="false" name="status_bar_camera">camera</string>
<string translatable="false" name="status_bar_airplane">airplane</string>
+ <string translatable="false" name="status_bar_no_calling">no_calling</string>
<string translatable="false" name="status_bar_sensors_off">sensors_off</string>
<string translatable="false" name="status_bar_screen_record">screen_record</string>
@@ -4600,4 +4602,14 @@
<!-- If true, attach the navigation bar to the app during app transition -->
<bool name="config_attachNavBarToAppDuringTransition">false</bool>
+
+ <!-- Flag indicating that the media framework should play a back sound when a back-transition
+ happens that doesn't result in bringing the home task to the front.
+ This is currently only used on TV. -->
+ <bool name="config_enableBackSound">false</bool>
+
+ <!-- Chooser image editing activity. Must handle ACTION_EDIT image/png intents.
+ If omitted, image editing will not be offered via Chooser.
+ This name is in the ComponentName flattened format (package/class) [DO NOT TRANSLATE] -->
+ <string name="config_systemImageEditor" translatable="false"></string>
</resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index a12d2a9..a4c7293 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -206,6 +206,9 @@
<!-- Marks the "nearby" button in the ChooserActivity -->
<item type="id" name="chooser_nearby_button" />
+ <!-- Marks the "edit" button in the ChooserActivity -->
+ <item type="id" name="chooser_edit_button" />
+
<!-- Accessibility action identifier for {@link android.accessibilityservice.AccessibilityService#GLOBAL_ACTION_BACK}. -->
<item type="id" name="accessibilitySystemActionBack" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0958434..bac50f1 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3047,9 +3047,14 @@
<public name="rollbackDataPolicy" />
<public name="allowClickWhenDisabled" />
<public name="windowLayoutAffinity" />
+ <public name="canPauseRecording" />
<!-- @hide -->
<public name="windowBackgroundBlurRadius"/>
<public name="requireDeviceScreenOn" />
+ <public name="pathSuffix" />
+ <public name="sspSuffix" />
+ <public name="pathAdvancedPattern" />
+ <public name="sspAdvancedPattern" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
@@ -3058,6 +3063,34 @@
<public-group type="color" first-id="0x0106001d">
<!-- color definitions go here -->
+
+ <!-- Material design dynamic system palette:-->
+ <!-- Dominant color -->
+ <public name="system_main_0" />
+ <public name="system_main_50" />
+ <public name="system_main_100" />
+ <public name="system_main_200" />
+ <public name="system_main_300" />
+ <public name="system_main_400" />
+ <public name="system_main_500" />
+ <public name="system_main_600" />
+ <public name="system_main_700" />
+ <public name="system_main_800" />
+ <public name="system_main_900" />
+ <public name="system_main_1000" />
+ <!-- Accent color -->
+ <public name="system_accent_0" />
+ <public name="system_accent_50" />
+ <public name="system_accent_100" />
+ <public name="system_accent_200" />
+ <public name="system_accent_300" />
+ <public name="system_accent_400" />
+ <public name="system_accent_500" />
+ <public name="system_accent_600" />
+ <public name="system_accent_700" />
+ <public name="system_accent_800" />
+ <public name="system_accent_900" />
+ <public name="system_accent_1000" />
</public-group>
<public-group type="dimen" first-id="0x01050008">
diff --git a/core/res/res/values/required_apps_managed_device.xml b/core/res/res/values/required_apps_managed_device.xml
index e17d214..c455bd8 100644
--- a/core/res/res/values/required_apps_managed_device.xml
+++ b/core/res/res/values/required_apps_managed_device.xml
@@ -28,5 +28,6 @@
<item>com.android.providers.downloads</item>
<item>com.android.providers.downloads.ui</item>
<item>com.android.documentsui</item>
+ <item>com.android.cellbroadcastreceiver</item>
</string-array>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5715b31..317a76f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -110,7 +110,7 @@
<!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
<string name="ClipMmi">Incoming Caller ID</string>
<!-- Displayed as the title for a success/failure report enabling/disabling caller ID. -->
- <string name="ClirMmi">Outgoing Caller ID</string>
+ <string name="ClirMmi">Hide Outgoing Caller ID</string>
<!-- Displayed as the title for a success/failure report enabling/disabling connected line ID. -->
<string name="ColpMmi">Connected Line ID</string>
<!-- Displayed as the title for a success/failure report enabling/disabling connected line ID restriction. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 96ebdaa..12acfd7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2045,6 +2045,7 @@
<java-symbol type="string" name="car_mode_disable_notification_message" />
<java-symbol type="string" name="car_mode_disable_notification_title" />
<java-symbol type="string" name="chooser_wallpaper" />
+ <java-symbol type="string" name="config_systemImageEditor" />
<java-symbol type="string" name="config_datause_iface" />
<java-symbol type="string" name="config_activityRecognitionHardwarePackageName" />
<java-symbol type="string" name="config_fusedLocationProviderPackageName" />
@@ -2946,6 +2947,7 @@
<java-symbol type="string" name="status_bar_secure" />
<java-symbol type="string" name="status_bar_clock" />
<java-symbol type="string" name="status_bar_airplane" />
+ <java-symbol type="string" name="status_bar_no_calling" />
<java-symbol type="string" name="status_bar_mobile" />
<java-symbol type="string" name="status_bar_ethernet" />
<java-symbol type="string" name="status_bar_vpn" />
@@ -3895,6 +3897,7 @@
<java-symbol type="drawable" name="chooser_dialog_background" />
<java-symbol type="id" name="chooser_copy_button" />
<java-symbol type="id" name="chooser_nearby_button" />
+ <java-symbol type="id" name="chooser_edit_button" />
<java-symbol type="layout" name="chooser_action_button" />
<java-symbol type="dimen" name="chooser_action_button_icon_size" />
<java-symbol type="string" name="config_defaultNearbySharingComponent" />
@@ -4142,4 +4145,6 @@
<java-symbol type="dimen" name="accessibility_focus_highlight_stroke_width" />
<java-symbol type="bool" name="config_attachNavBarToAppDuringTransition" />
+
+ <java-symbol type="bool" name="config_enableBackSound" />
</resources>
diff --git a/core/res/res/xml/audio_assets.xml b/core/res/res/xml/audio_assets.xml
index af5798a..57789e1 100644
--- a/core/res/res/xml/audio_assets.xml
+++ b/core/res/res/xml/audio_assets.xml
@@ -19,21 +19,18 @@
<!-- Mapping of UI sound effects to audio assets under /system/media/audio/ui.
Modify this file to override default sound assets.
- Currently only touch sounds can be overridden. Other groups can be added
- in the future for other UI sounds like camera, lock, dock...
-->
<audio_assets version="1.0">
- <group name="touch_sounds">
- <asset id="FX_KEY_CLICK" file="Effect_Tick.ogg"/>
- <asset id="FX_FOCUS_NAVIGATION_UP" file="Effect_Tick.ogg"/>
- <asset id="FX_FOCUS_NAVIGATION_DOWN" file="Effect_Tick.ogg"/>
- <asset id="FX_FOCUS_NAVIGATION_LEFT" file="Effect_Tick.ogg"/>
- <asset id="FX_FOCUS_NAVIGATION_RIGHT" file="Effect_Tick.ogg"/>
- <asset id="FX_KEYPRESS_STANDARD" file="KeypressStandard.ogg"/>
- <asset id="FX_KEYPRESS_SPACEBAR" file="KeypressSpacebar.ogg"/>
- <asset id="FX_KEYPRESS_DELETE" file="KeypressDelete.ogg"/>
- <asset id="FX_KEYPRESS_RETURN" file="KeypressReturn.ogg"/>
- <asset id="FX_KEYPRESS_INVALID" file="KeypressInvalid.ogg"/>
- </group>
+ <asset id="FX_KEY_CLICK" file="Effect_Tick.ogg"/>
+ <asset id="FX_FOCUS_NAVIGATION_UP" file="Effect_Tick.ogg"/>
+ <asset id="FX_FOCUS_NAVIGATION_DOWN" file="Effect_Tick.ogg"/>
+ <asset id="FX_FOCUS_NAVIGATION_LEFT" file="Effect_Tick.ogg"/>
+ <asset id="FX_FOCUS_NAVIGATION_RIGHT" file="Effect_Tick.ogg"/>
+ <asset id="FX_KEYPRESS_STANDARD" file="KeypressStandard.ogg"/>
+ <asset id="FX_KEYPRESS_SPACEBAR" file="KeypressSpacebar.ogg"/>
+ <asset id="FX_KEYPRESS_DELETE" file="KeypressDelete.ogg"/>
+ <asset id="FX_KEYPRESS_RETURN" file="KeypressReturn.ogg"/>
+ <asset id="FX_KEYPRESS_INVALID" file="KeypressInvalid.ogg"/>
+ <asset id="FX_BACK" file="Effect_Tick.ogg"/>
</audio_assets>
diff --git a/core/tests/PackageInstallerSessions/src/android/content/pm/PackageSessionTests.kt b/core/tests/PackageInstallerSessions/src/android/content/pm/PackageSessionTests.kt
index b410189..18d82af 100644
--- a/core/tests/PackageInstallerSessions/src/android/content/pm/PackageSessionTests.kt
+++ b/core/tests/PackageInstallerSessions/src/android/content/pm/PackageSessionTests.kt
@@ -78,7 +78,8 @@
}
fun makeIntentSender(sessionId: Int) = PendingIntent.getBroadcast(context, sessionId,
- Intent(INTENT_ACTION), PendingIntent.FLAG_UPDATE_CURRENT).intentSender
+ Intent(INTENT_ACTION),
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE_UNAUDITED).intentSender
fun getResult(unit: TimeUnit, timeout: Long) = results.poll(timeout, unit)
diff --git a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
index a5ef2b4..d8ed805 100644
--- a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
+++ b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
@@ -23,7 +23,10 @@
import static org.junit.Assert.fail;
import android.Manifest;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.os.BugreportManager;
import android.os.BugreportManager.BugreportCallback;
import android.os.BugreportParams;
@@ -31,7 +34,9 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.StrictMode;
+import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -53,10 +58,11 @@
import org.junit.runners.JUnit4;
import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
-
/**
* Tests for BugreportManager API.
*/
@@ -67,8 +73,16 @@
private static final String TAG = "BugreportManagerTest";
private static final long BUGREPORT_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(10);
+ private static final long DUMPSTATE_STARTUP_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(10);
private static final long UIAUTOMATOR_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(10);
+ // Sent by Shell when its bugreport finishes (contains final bugreport/screenshot file name
+ // associated with the bugreport).
+ private static final String INTENT_BUGREPORT_FINISHED =
+ "com.android.internal.intent.action.BUGREPORT_FINISHED";
+ private static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT";
+ private static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
+
private Handler mHandler;
private Executor mExecutor;
private BugreportManager mBrm;
@@ -212,6 +226,48 @@
}
@Test
+ public void cancelBugreport_noReportStarted() throws Exception {
+ // Without the native DumpstateService running, we don't get a SecurityException.
+ mBrm.cancelBugreport();
+ }
+
+ @LargeTest
+ @Test
+ public void cancelBugreport_fromDifferentUid() throws Exception {
+ assertThat(Process.myUid()).isNotEqualTo(Process.SHELL_UID);
+
+ // Start a bugreport through ActivityManager's shell command - this starts a BR from the
+ // shell UID rather than our own.
+ BugreportBroadcastReceiver br = new BugreportBroadcastReceiver();
+ InstrumentationRegistry.getContext()
+ .registerReceiver(br, new IntentFilter(INTENT_BUGREPORT_FINISHED));
+ UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ .executeShellCommand("am bug-report");
+
+ // The command triggers the report through a broadcast, so wait until dumpstate actually
+ // starts up, which may take a bit.
+ waitTillDumpstateRunningOrTimeout();
+
+ try {
+ mBrm.cancelBugreport();
+ fail("Expected cancelBugreport to throw SecurityException when report started by "
+ + "different UID");
+ } catch (SecurityException expected) {
+ } finally {
+ // Do this in the finally block so that even if this test case fails, we don't break
+ // other test cases unexpectedly due to the still-running shell report.
+ try {
+ // The shell's BR is still running and should complete successfully.
+ br.waitForBugreportFinished();
+ } finally {
+ // The latch may fail for a number of reasons but we still need to unregister the
+ // BroadcastReceiver.
+ InstrumentationRegistry.getContext().unregisterReceiver(br);
+ }
+ }
+ }
+
+ @Test
public void insufficientPermissions_throwsException() throws Exception {
dropPermissions();
@@ -347,6 +403,28 @@
.adoptShellPermissionIdentity(Manifest.permission.DUMP);
}
+ private static boolean isDumpstateRunning() {
+ String[] output;
+ try {
+ output =
+ UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ .executeShellCommand("ps -A -o NAME | grep dumpstate")
+ .trim()
+ .split("\n");
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to check if dumpstate is running", e);
+ return false;
+ }
+ for (String line : output) {
+ // Check for an exact match since there may be other things that contain "dumpstate" as
+ // a substring (e.g. the dumpstate HAL).
+ if (TextUtils.equals("dumpstate", line)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static void assertFdIsClosed(ParcelFileDescriptor pfd) {
try {
int fd = pfd.getFd();
@@ -365,18 +443,25 @@
return System.currentTimeMillis();
}
- private static boolean shouldTimeout(long startTimeMs) {
- return now() - startTimeMs >= BUGREPORT_TIMEOUT_MS;
+ private static void waitTillDumpstateRunningOrTimeout() throws Exception {
+ long startTimeMs = now();
+ while (!isDumpstateRunning()) {
+ Thread.sleep(500 /* .5s */);
+ if (now() - startTimeMs >= DUMPSTATE_STARTUP_TIMEOUT_MS) {
+ break;
+ }
+ Log.d(TAG, "Waited " + (now() - startTimeMs) + "ms for dumpstate to start");
+ }
}
private static void waitTillDoneOrTimeout(BugreportCallbackImpl callback) throws Exception {
long startTimeMs = now();
while (!callback.isDone()) {
Thread.sleep(1000 /* 1s */);
- if (shouldTimeout(startTimeMs)) {
+ if (now() - startTimeMs >= BUGREPORT_TIMEOUT_MS) {
break;
}
- Log.d(TAG, "Waited " + (now() - startTimeMs) + "ms");
+ Log.d(TAG, "Waited " + (now() - startTimeMs) + "ms for bugreport to finish");
}
}
@@ -451,6 +536,36 @@
assertTrue(device.wait(Until.gone(consentTitleObj), UIAUTOMATOR_TIMEOUT_MS));
}
+ private class BugreportBroadcastReceiver extends BroadcastReceiver {
+ Intent mBugreportFinishedIntent = null;
+ final CountDownLatch mLatch;
+
+ BugreportBroadcastReceiver() {
+ mLatch = new CountDownLatch(1);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ setBugreportFinishedIntent(intent);
+ mLatch.countDown();
+ }
+
+ private void setBugreportFinishedIntent(Intent intent) {
+ mBugreportFinishedIntent = intent;
+ }
+
+ public Intent getBugreportFinishedIntent() {
+ return mBugreportFinishedIntent;
+ }
+
+ public void waitForBugreportFinished() throws Exception {
+ if (!mLatch.await(BUGREPORT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ throw new Exception("Failed to receive BUGREPORT_FINISHED in "
+ + BUGREPORT_TIMEOUT_MS + " ms.");
+ }
+ }
+ }
+
/**
* A rule to change strict mode vm policy temporarily till test method finished.
*
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 109cff9..252938a 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -186,8 +186,8 @@
@Test
public void allPendingIntents_recollectedAfterReusingBuilder() {
- PendingIntent intent1 = PendingIntent.getActivity(mContext, 0, new Intent("test1"), 0);
- PendingIntent intent2 = PendingIntent.getActivity(mContext, 0, new Intent("test2"), 0);
+ PendingIntent intent1 = PendingIntent.getActivity(mContext, 0, new Intent("test1"), PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ PendingIntent intent2 = PendingIntent.getActivity(mContext, 0, new Intent("test2"), PendingIntent.FLAG_MUTABLE_UNAUDITED);
Notification.Builder builder = new Notification.Builder(mContext, "channel");
builder.setContentIntent(intent1);
@@ -206,7 +206,7 @@
@Test
public void allPendingIntents_containsCustomRemoteViews() {
- PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent("test"), 0);
+ PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent("test"), PendingIntent.FLAG_MUTABLE_UNAUDITED);
RemoteViews contentView = new RemoteViews(mContext.getPackageName(), 0 /* layoutId */);
contentView.setOnClickPendingIntent(1 /* id */, intent);
diff --git a/core/tests/coretests/src/android/app/activity/IntentSenderTest.java b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
index 19ddb52..05775bc 100644
--- a/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
+++ b/core/tests/coretests/src/android/app/activity/IntentSenderTest.java
@@ -32,7 +32,7 @@
registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED), PERMISSION_GRANTED);
addIntermediate("after-register");
PendingIntent is = PendingIntent.getBroadcast(getContext(), 0,
- makeBroadcastIntent(BROADCAST_REGISTERED), 0);
+ makeBroadcastIntent(BROADCAST_REGISTERED), PendingIntent.FLAG_MUTABLE_UNAUDITED);
is.send();
waitForResultOrThrow(BROADCAST_TIMEOUT);
is.cancel();
@@ -52,7 +52,7 @@
}
};
- PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
+ PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
is.send(Activity.RESULT_CANCELED, finish, null);
waitForResultOrThrow(BROADCAST_TIMEOUT);
is.cancel();
@@ -61,7 +61,7 @@
public void testLocalReceivePermissionGranted() throws Exception {
setExpectedReceivers(new String[]{RECEIVER_LOCAL});
PendingIntent is = PendingIntent.getBroadcast(getContext(), 0,
- makeBroadcastIntent(BROADCAST_LOCAL_GRANTED), 0);
+ makeBroadcastIntent(BROADCAST_LOCAL_GRANTED), PendingIntent.FLAG_MUTABLE_UNAUDITED);
is.send();
waitForResultOrThrow(BROADCAST_TIMEOUT);
is.cancel();
@@ -79,7 +79,7 @@
}
};
- PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
+ PendingIntent is = PendingIntent.getBroadcast(getContext(), 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
is.send(Activity.RESULT_CANCELED, finish, null);
waitForResultOrThrow(BROADCAST_TIMEOUT);
is.cancel();
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
new file mode 100644
index 0000000..986079f
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/PutDocumentsRequestTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.appsearch;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+
+import java.util.Set;
+
+public class PutDocumentsRequestTest {
+
+ @Test
+ public void addGenericDocument_byCollection() {
+ Set<AppSearchEmail> emails =
+ ImmutableSet.of(
+ new AppSearchEmail.Builder("test1").build(),
+ new AppSearchEmail.Builder("test2").build());
+ PutDocumentsRequest request =
+ new PutDocumentsRequest.Builder().addGenericDocument(emails).build();
+
+ assertThat(request.getDocuments().get(0).getUri()).isEqualTo("test1");
+ assertThat(request.getDocuments().get(1).getUri()).isEqualTo("test2");
+ }
+}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
index b3caecc..c8cee85 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
@@ -16,6 +16,7 @@
package android.app.appsearch;
+
import static com.google.common.truth.Truth.assertThat;
import android.os.Bundle;
@@ -26,6 +27,7 @@
import java.util.Map;
public class SearchSpecTest {
+
@Test
public void testGetBundle() {
SearchSpec searchSpec =
@@ -33,6 +35,7 @@
.setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
.addNamespace("namespace1", "namespace2")
.addSchemaType("schemaTypes1", "schemaTypes2")
+ .addFilterPackageNames("package1", "package2")
.setSnippetCount(5)
.setSnippetCountPerProperty(10)
.setMaxSnippetSize(15)
@@ -48,6 +51,8 @@
.containsExactly("namespace1", "namespace2");
assertThat(bundle.getStringArrayList(SearchSpec.SCHEMA_TYPE_FIELD))
.containsExactly("schemaTypes1", "schemaTypes2");
+ assertThat(bundle.getStringArrayList(SearchSpec.PACKAGE_NAME_FIELD))
+ .containsExactly("package1", "package2");
assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_FIELD)).isEqualTo(5);
assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_PER_PROPERTY_FIELD)).isEqualTo(10);
assertThat(bundle.getInt(SearchSpec.MAX_SNIPPET_FIELD)).isEqualTo(15);
@@ -62,15 +67,26 @@
SearchSpec searchSpec =
new SearchSpec.Builder()
.setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
- .addProjectionTypePropertyPaths("TypeA", "field1", "field2.subfield2")
- .addProjectionTypePropertyPaths("TypeB", "field7")
- .addProjectionTypePropertyPaths("TypeC")
+ .addProjection("TypeA", "field1", "field2.subfield2")
+ .addProjection("TypeB", "field7")
+ .addProjection("TypeC")
.build();
- Map<String, List<String>> typePropertyPathMap = searchSpec.getProjectionTypePropertyPaths();
+ Map<String, List<String>> typePropertyPathMap = searchSpec.getProjections();
assertThat(typePropertyPathMap.keySet()).containsExactly("TypeA", "TypeB", "TypeC");
assertThat(typePropertyPathMap.get("TypeA")).containsExactly("field1", "field2.subfield2");
assertThat(typePropertyPathMap.get("TypeB")).containsExactly("field7");
assertThat(typePropertyPathMap.get("TypeC")).isEmpty();
}
+
+ @Test
+ public void testGetRankingStrategy() {
+ SearchSpec searchSpec =
+ new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .setRankingStrategy(SearchSpec.RANKING_STRATEGY_RELEVANCE_SCORE)
+ .build();
+ assertThat(searchSpec.getRankingStrategy())
+ .isEqualTo(SearchSpec.RANKING_STRATEGY_RELEVANCE_SCORE);
+ }
}
diff --git a/core/tests/coretests/src/android/content/OWNERS b/core/tests/coretests/src/android/content/OWNERS
index 912db1e..696aa11 100644
--- a/core/tests/coretests/src/android/content/OWNERS
+++ b/core/tests/coretests/src/android/content/OWNERS
@@ -1,3 +1,4 @@
per-file ContextTest.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
+per-file AppSearchPersonTest.java = file:/core/java/android/content/pm/SHORTCUT_OWNERS
per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 05ff218..465ea17 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -48,7 +48,9 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
+import java.util.HashMap;
import java.util.Locale;
+import java.util.Map;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -145,9 +147,13 @@
} catch (IOException e) {
throw new RuntimeException(e);
}
+ Map<String, File> updatableFontMap = new HashMap<>();
+ for (File file : new File(TEST_UPDATABLE_FONT_DIR).listFiles()) {
+ updatableFontMap.put(file.getName(), file);
+ }
final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(TEST_FONTS_XML,
- TEST_FONT_DIR, TEST_UPDATABLE_FONT_DIR, oemCustomization, fallbackMap);
+ TEST_FONT_DIR, updatableFontMap, oemCustomization, fallbackMap);
Typeface.initSystemDefaultTypefaces(fontMap, fallbackMap, aliases);
}
diff --git a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
index 8c47fcb..6186192 100644
--- a/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
+++ b/core/tests/coretests/src/android/service/settings/suggestions/SuggestionTest.java
@@ -48,7 +48,7 @@
public void setUp() {
final Context context = InstrumentationRegistry.getContext();
mTestIntent = PendingIntent.getActivity(context, 0 /* requestCode */,
- new Intent(), 0 /* flags */);
+ new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED /* flags */);
mIcon = Icon.createWithBitmap(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888));
}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index af13cc0..2770ed8 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -45,6 +45,7 @@
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -681,6 +682,19 @@
}
@Test
+ public void testNotifyCaptionInsetsOnlyChange() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ final InsetsState state = new InsetsState(mController.getState(), true);
+ reset(mTestHost);
+ mController.setCaptionInsetsHeight(100);
+ verify(mTestHost).notifyInsetsChanged();
+ reset(mTestHost);
+ mController.setCaptionInsetsHeight(0);
+ verify(mTestHost).notifyInsetsChanged();
+ });
+ }
+
+ @Test
public void testRequestedState() {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
final InsetsState state = mTestHost.getRequestedState();
diff --git a/core/tests/coretests/src/android/view/autofill/OWNERS b/core/tests/coretests/src/android/view/autofill/OWNERS
new file mode 100644
index 0000000..9a30e82
--- /dev/null
+++ b/core/tests/coretests/src/android/view/autofill/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 351486
+
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/tests/coretests/src/android/view/contentcapture/OWNERS b/core/tests/coretests/src/android/view/contentcapture/OWNERS
new file mode 100644
index 0000000..24561c5
--- /dev/null
+++ b/core/tests/coretests/src/android/view/contentcapture/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 544200
+
+include /core/java/android/view/contentcapture/OWNERS
diff --git a/core/tests/coretests/src/android/view/textclassifier/ConversationActionTest.java b/core/tests/coretests/src/android/view/textclassifier/ConversationActionTest.java
index 6b62635..07eeae0 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ConversationActionTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ConversationActionTest.java
@@ -39,7 +39,7 @@
@Test
public void toBuilder() {
final Context context = InstrumentationRegistry.getTargetContext();
- final PendingIntent intent = PendingIntent.getActivity(context, 0, new Intent(), 0);
+ final PendingIntent intent = PendingIntent.getActivity(context, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED);
final Icon icon = Icon.createWithData(new byte[]{0}, 0, 1);
final Bundle extras = new Bundle();
extras.putInt("key", 5);
diff --git a/core/tests/coretests/src/android/view/textclassifier/OWNERS b/core/tests/coretests/src/android/view/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
index cf742b0..db62e17 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
@@ -79,7 +79,7 @@
final String primaryDescription = "primaryDescription";
final Intent primaryIntent = new Intent("primaryIntentAction");
final PendingIntent primaryPendingIntent = PendingIntent.getActivity(context, 0,
- primaryIntent, 0);
+ primaryIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
final RemoteAction remoteAction0 = new RemoteAction(primaryIcon, primaryLabel,
primaryDescription, primaryPendingIntent);
@@ -88,7 +88,7 @@
final String secondaryDescription = "secondaryDescription";
final Intent secondaryIntent = new Intent("secondaryIntentAction");
final PendingIntent secondaryPendingIntent = PendingIntent.getActivity(context, 0,
- secondaryIntent, 0);
+ secondaryIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
final RemoteAction remoteAction1 = new RemoteAction(secondaryIcon, secondaryLabel,
secondaryDescription, secondaryPendingIntent);
@@ -156,7 +156,7 @@
final int iconColor = Color.RED;
final String label = "label";
final PendingIntent pendingIntent = PendingIntent.getActivity(
- context, 0, new Intent("ACTION_0"), 0);
+ context, 0, new Intent("ACTION_0"), PendingIntent.FLAG_MUTABLE_UNAUDITED);
final RemoteAction remoteAction = new RemoteAction(
generateTestIcon(width, height, iconColor),
label,
@@ -239,7 +239,7 @@
.setIntent(new Intent("action"))
.setOnClickListener(view -> { })
.addAction(new RemoteAction(icon1, "title1", "desc1",
- PendingIntent.getActivity(context, 0, new Intent("action1"), 0)))
+ PendingIntent.getActivity(context, 0, new Intent("action1"), PendingIntent.FLAG_MUTABLE_UNAUDITED)))
.addAction(new RemoteAction(icon1, "title2", "desc2",
PendingIntent.getActivity(context, 0, new Intent("action2"), 0)))
.setEntityType(TextClassifier.TYPE_EMAIL, 0.5f)
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
index 82788c8..5def552 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
@@ -16,14 +16,24 @@
package android.view.textclassifier;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import android.app.PendingIntent;
+import android.app.RemoteAction;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -107,4 +117,46 @@
assertEquals(1, resultSystemTcMetadata.getUserId());
assertFalse(resultSystemTcMetadata.useDefaultTextClassifier());
}
+
+ @Test
+ public void testToBuilder() {
+ final Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ final int startIndex = 13;
+ final int endIndex = 37;
+ final String id = "id";
+ final Icon icon1 = generateTestIcon(5, 5, Color.RED);
+
+ final TextClassification classification = new TextClassification.Builder()
+ .addAction(new RemoteAction(icon1, "title1", "desc1",
+ PendingIntent.getActivity(context, 0, new Intent("action1"), 0)))
+ .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f)
+ .build();
+ final TextSelection textSelection = new TextSelection.Builder(startIndex, endIndex)
+ .setId(id)
+ .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f)
+ .setExtras(BUNDLE)
+ .setTextClassification(classification)
+ .build();
+
+ final TextSelection fromBuilder = textSelection.toBuilder().build();
+
+ assertThat(fromBuilder.getId()).isEqualTo(textSelection.getId());
+ assertThat(fromBuilder.getSelectionStartIndex())
+ .isEqualTo(textSelection.getSelectionStartIndex());
+ assertThat(fromBuilder.getSelectionEndIndex())
+ .isEqualTo(textSelection.getSelectionEndIndex());
+ assertThat(fromBuilder.getTextClassification())
+ .isSameInstanceAs(textSelection.getTextClassification());
+ assertThat(fromBuilder.getExtras()).isSameInstanceAs(textSelection.getExtras());
+ }
+
+ private Icon generateTestIcon(int width, int height, int colorValue) {
+ final int numPixels = width * height;
+ final int[] colors = new int[numPixels];
+ for (int i = 0; i < numPixels; ++i) {
+ colors[i] = colorValue;
+ }
+ final Bitmap bitmap = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
+ return Icon.createWithBitmap(bitmap);
+ }
}
diff --git a/core/tests/coretests/src/android/widget/AbsSeekBarTest.java b/core/tests/coretests/src/android/widget/AbsSeekBarTest.java
index aec6096..5371a0f 100644
--- a/core/tests/coretests/src/android/widget/AbsSeekBarTest.java
+++ b/core/tests/coretests/src/android/widget/AbsSeekBarTest.java
@@ -60,35 +60,35 @@
@Test
public void testExclusionForThumb_limitedTo48dp() {
mBar.setPadding(10, 10, 10, 10);
- mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setThumb(newThumb(dpToPxSize(20)));
mBar.setMin(0);
mBar.setMax(100);
mBar.setProgress(50);
- measureAndLayout(dpToPx(200), dpToPx(100));
+ measureAndLayout(dpToPxSize(200), dpToPxSize(100));
List<Rect> exclusions = mBar.getSystemGestureExclusionRects();
assertEquals("exclusions should be size 1, but was " + exclusions, 1, exclusions.size());
assertEquals("exclusion should be centered on thumb",
center(mBar), center(exclusions.get(0)));
- assertEquals("exclusion should be 48dp high", dpToPx(48), exclusions.get(0).height());
- assertEquals("exclusion should be 48dp wide", dpToPx(48), exclusions.get(0).width());
+ assertEquals("exclusion should be 48dp high", dpToPxSize(48), exclusions.get(0).height());
+ assertEquals("exclusion should be 48dp wide", dpToPxSize(48), exclusions.get(0).width());
}
@Test
public void testExclusionForThumb_limitedToHeight() {
mBar.setPadding(10, 10, 10, 10);
- mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setThumb(newThumb(dpToPxSize(20)));
mBar.setMin(0);
mBar.setMax(100);
mBar.setProgress(50);
- measureAndLayout(dpToPx(200), dpToPx(32));
+ measureAndLayout(dpToPxSize(200), dpToPxSize(32));
List<Rect> exclusions = mBar.getSystemGestureExclusionRects();
assertEquals("exclusions should be size 1, but was " + exclusions, 1, exclusions.size());
assertEquals("exclusion should be centered on thumb",
center(mBar), center(exclusions.get(0)));
- assertEquals("exclusion should be 32dp high", dpToPx(32), exclusions.get(0).height());
- assertEquals("exclusion should be 32dp wide", dpToPx(32), exclusions.get(0).width());
+ assertEquals("exclusion should be 32dp high", dpToPxSize(32), exclusions.get(0).height());
+ assertEquals("exclusion should be 32dp wide", dpToPxSize(32), exclusions.get(0).width());
}
@Test
@@ -96,11 +96,11 @@
mBar.setSystemGestureExclusionRects(Arrays.asList(new Rect(1, 2, 3, 4)));
mBar.setPadding(10, 10, 10, 10);
- mBar.setThumb(newThumb(dpToPx(20)));
+ mBar.setThumb(newThumb(dpToPxSize(20)));
mBar.setMin(0);
mBar.setMax(100);
mBar.setProgress(50);
- measureAndLayout(dpToPx(200), dpToPx(32));
+ measureAndLayout(dpToPxSize(200), dpToPxSize(32));
assertThat(mBar.getSystemGestureExclusionRects(), hasItem(new Rect(1, 2, 3, 4)));
assertThat(mBar.getSystemGestureExclusionRects(), hasSize(2));
@@ -130,7 +130,7 @@
mBar.layout(0, 0, wPx, hPx);
}
- private int dpToPx(int dp) {
- return (int) (mContext.getResources().getDisplayMetrics().density * dp);
+ private int dpToPxSize(int dp) {
+ return (int) (mContext.getResources().getDisplayMetrics().density * dp + 0.5f);
}
}
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 8cb7e1b..059c764 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -406,7 +406,7 @@
RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
for (int i = 1; i < 10; i++) {
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
- new Intent("android.widget.RemoteViewsTest_" + i), PendingIntent.FLAG_ONE_SHOT);
+ new Intent("android.widget.RemoteViewsTest_" + i), PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
views.setOnClickPendingIntent(i, pi);
}
try {
@@ -422,7 +422,7 @@
RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
- new Intent("test"), PendingIntent.FLAG_ONE_SHOT);
+ new Intent("test"), PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
views.setOnClickPendingIntent(1, pi);
RemoteViews withCookie = parcelAndRecreateWithPendingIntentCookie(views, whitelistToken);
@@ -454,7 +454,7 @@
RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test);
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0,
new Intent("android.widget.RemoteViewsTest_shared_element"),
- PendingIntent.FLAG_ONE_SHOT);
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
views.setOnClickResponse(R.id.image, RemoteViews.RemoteResponse.fromPendingIntent(pi)
.addSharedElement(0, "e0")
.addSharedElement(1, "e1")
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 787879a..d9012f64 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -638,6 +638,59 @@
}
+
+ @Test
+ public void testEditImageLogs() throws Exception {
+ Intent sendIntent = createSendImageIntent(
+ Uri.parse("android.resource://com.android.frameworks.coretests/"
+ + com.android.frameworks.coretests.R.drawable.test320x240));
+
+ sOverrides.previewThumbnail = createBitmap();
+ sOverrides.isImageType = true;
+
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+
+ when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
+ Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+
+ onView(withId(R.id.chooser_edit_button)).check(matches(isDisplayed()));
+ onView(withId(R.id.chooser_edit_button)).perform(click());
+
+ ChooserActivityLoggerFake logger =
+ (ChooserActivityLoggerFake) activity.getChooserActivityLogger();
+ // first one should be SHARESHEET_TRIGGERED uievent
+ assertThat(logger.get(0).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(0).event.getId(),
+ is(ChooserActivityLogger.SharesheetStandardEvent.SHARESHEET_TRIGGERED.getId()));
+ // second one should be SHARESHEET_STARTED event
+ assertThat(logger.get(1).atomId, is(FrameworkStatsLog.SHARESHEET_STARTED));
+ assertThat(logger.get(1).intent, is(Intent.ACTION_SEND));
+ assertThat(logger.get(1).mimeType, is("image/png"));
+ assertThat(logger.get(1).packageName, is("com.android.frameworks.coretests"));
+ assertThat(logger.get(1).appProvidedApp, is(0));
+ assertThat(logger.get(1).appProvidedDirect, is(0));
+ assertThat(logger.get(1).isWorkprofile, is(false));
+ assertThat(logger.get(1).previewType, is(1));
+ // third one should be SHARESHEET_APP_LOAD_COMPLETE uievent
+ assertThat(logger.get(2).atomId, is(FrameworkStatsLog.UI_EVENT_REPORTED));
+ assertThat(logger.get(2).event.getId(),
+ is(ChooserActivityLogger
+ .SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE.getId()));
+ // fourth and fifth are just artifacts of test set-up
+ // sixth one should be ranking atom with SHARESHEET_EDIT_TARGET_SELECTED event
+ assertThat(logger.get(5).atomId, is(FrameworkStatsLog.RANKING_SELECTED));
+ assertThat(logger.get(5).targetType,
+ is(ChooserActivityLogger
+ .SharesheetTargetSelectedEvent.SHARESHEET_EDIT_TARGET_SELECTED.getId()));
+ }
+
+
@Test
public void oneVisibleImagePreview() throws InterruptedException {
Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
@@ -2202,6 +2255,19 @@
return sendIntent;
}
+ private Intent createSendImageIntent(Uri imageThumbnail) {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_STREAM, imageThumbnail);
+ sendIntent.setType("image/png");
+ if (imageThumbnail != null) {
+ ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
+ sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
+ }
+
+ return sendIntent;
+ }
+
private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
diff --git a/core/tests/coretests/src/com/android/internal/app/OWNERS b/core/tests/coretests/src/com/android/internal/app/OWNERS
new file mode 100644
index 0000000..6888be3
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/app/OWNERS
@@ -0,0 +1 @@
+include /core/java/com/android/internal/app/OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index 7f7bfa3..10aaf31 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -16,6 +16,12 @@
package com.android.internal.jank;
+import static android.view.SurfaceControl.JankData.JANK_APP_DEADLINE_MISSED;
+import static android.view.SurfaceControl.JankData.JANK_NONE;
+import static android.view.SurfaceControl.JankData.JANK_SURFACEFLINGER_DEADLINE_MISSED;
+
+import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper;
+import static com.android.internal.jank.FrameTracker.ViewRootWrapper;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
import static com.google.common.truth.Truth.assertThat;
@@ -23,6 +29,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.verify;
@@ -30,12 +37,17 @@
import android.os.Handler;
import android.view.FrameMetrics;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.JankData;
+import android.view.SurfaceControl.JankData.JankType;
+import android.view.SurfaceControl.OnJankDataListener;
import android.view.View;
import android.view.ViewAttachTestActivity;
import androidx.test.filters.SmallTest;
import androidx.test.rule.ActivityTestRule;
+import com.android.internal.jank.FrameTracker.ChoreographerWrapper;
import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
import com.android.internal.jank.InteractionJankMonitor.Session;
@@ -43,6 +55,7 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import java.util.concurrent.TimeUnit;
@@ -58,6 +71,11 @@
private FrameTracker mTracker;
private ThreadedRendererWrapper mRenderer;
private FrameMetricsWrapper mWrapper;
+ private SurfaceControlWrapper mSurfaceControlWrapper;
+ private ViewRootWrapper mViewRootWrapper;
+ private ChoreographerWrapper mChoreographer;
+ private ArgumentCaptor<OnJankDataListener> mListenerCapture;
+ private SurfaceControl mSurfaceControl;
@Before
public void setup() {
@@ -68,63 +86,116 @@
Handler handler = mRule.getActivity().getMainThreadHandler();
mWrapper = Mockito.spy(new FrameMetricsWrapper());
- // For simplicity - provide current timestamp anytime mWrapper asked for VSYNC_TIMESTAMP
- when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
- .then(unusedInvocation -> System.nanoTime());
mRenderer = Mockito.spy(new ThreadedRendererWrapper(view.getThreadedRenderer()));
doNothing().when(mRenderer).addObserver(any());
doNothing().when(mRenderer).removeObserver(any());
+ mSurfaceControl = new SurfaceControl.Builder().setName("Surface").build();
+ mViewRootWrapper = mock(ViewRootWrapper.class);
+ when(mViewRootWrapper.getSurfaceControl()).thenReturn(mSurfaceControl);
+ mSurfaceControlWrapper = mock(SurfaceControlWrapper.class);
+
+ mListenerCapture = ArgumentCaptor.forClass(OnJankDataListener.class);
+ doNothing().when(mSurfaceControlWrapper).addJankStatsListener(
+ mListenerCapture.capture(), any());
+ mChoreographer = mock(ChoreographerWrapper.class);
+
+
Session session = new Session(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
mTracker = Mockito.spy(
- new FrameTracker(session, handler, mRenderer, mWrapper,
+ new FrameTracker(session, handler, mRenderer, mViewRootWrapper,
+ mSurfaceControlWrapper, mChoreographer, mWrapper,
/*traceThresholdMissedFrames=*/ 1, /*traceThresholdFrameTimeMillis=*/ -1));
doNothing().when(mTracker).triggerPerfetto();
}
@Test
- public void testOnlyFirstFrameOverThreshold() {
+ public void testOnlyFirstWindowFrameOverThreshold() {
// Just provide current timestamp anytime mWrapper asked for VSYNC_TIMESTAMP
when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
.then(unusedInvocation -> System.nanoTime());
+ when(mChoreographer.getVsyncId()).thenReturn(100L);
mTracker.begin();
verify(mRenderer, only()).addObserver(any());
// send first frame with a long duration - should not be taken into account
- setupFirstFrameMockWithDuration(100);
- mTracker.onFrameMetricsAvailable(0);
+ sendFirstWindowFrame(100, JANK_APP_DEADLINE_MISSED, 100L);
// send another frame with a short duration - should not be considered janky
- setupOtherFrameMockWithDuration(5);
- mTracker.onFrameMetricsAvailable(0);
+ sendFirstWindowFrame(5, JANK_NONE, 101L);
// end the trace session, the last janky frame is after the end() so is discarded.
+ when(mChoreographer.getVsyncId()).thenReturn(101L);
mTracker.end();
- setupOtherFrameMockWithDuration(500);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(500, JANK_APP_DEADLINE_MISSED, 102L);
verify(mRenderer).removeObserver(any());
verify(mTracker, never()).triggerPerfetto();
}
@Test
- public void testOtherFrameOverThreshold() {
+ public void testSfJank() {
+ when(mChoreographer.getVsyncId()).thenReturn(100L);
mTracker.begin();
verify(mRenderer, only()).addObserver(any());
// send first frame - not janky
- setupFirstFrameMockWithDuration(4);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(4, JANK_NONE, 100L);
// send another frame - should be considered janky
- setupOtherFrameMockWithDuration(40);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(40, JANK_SURFACEFLINGER_DEADLINE_MISSED, 101L);
// end the trace session
+ when(mChoreographer.getVsyncId()).thenReturn(101L);
mTracker.end();
- setupOtherFrameMockWithDuration(5);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(4, JANK_NONE, 102L);
+
+ verify(mRenderer).removeObserver(any());
+
+ // We detected a janky frame - trigger Perfetto
+ verify(mTracker).triggerPerfetto();
+ }
+
+ @Test
+ public void testFirstFrameJankyNoTrigger() {
+ when(mChoreographer.getVsyncId()).thenReturn(100L);
+ mTracker.begin();
+ verify(mRenderer, only()).addObserver(any());
+
+ // send first frame - janky
+ sendFrame(40, JANK_APP_DEADLINE_MISSED, 100L);
+
+ // send another frame - not jank
+ sendFrame(4, JANK_NONE, 101L);
+
+ // end the trace session
+ when(mChoreographer.getVsyncId()).thenReturn(101L);
+ mTracker.end();
+ sendFrame(4, JANK_NONE, 102L);
+
+ verify(mRenderer).removeObserver(any());
+
+ // We detected a janky frame - trigger Perfetto
+ verify(mTracker, never()).triggerPerfetto();
+ }
+
+ @Test
+ public void testOtherFrameOverThreshold() {
+ when(mChoreographer.getVsyncId()).thenReturn(100L);
+ mTracker.begin();
+ verify(mRenderer, only()).addObserver(any());
+
+ // send first frame - not janky
+ sendFrame(4, JANK_NONE, 100L);
+
+ // send another frame - should be considered janky
+ sendFrame(40, JANK_APP_DEADLINE_MISSED, 101L);
+
+ // end the trace session
+ when(mChoreographer.getVsyncId()).thenReturn(101L);
+ mTracker.end();
+ sendFrame(4, JANK_NONE, 102L);
verify(mRenderer).removeObserver(any());
@@ -134,29 +205,23 @@
@Test
public void testLastFrameOverThresholdBeforeEnd() {
+ when(mChoreographer.getVsyncId()).thenReturn(100L);
mTracker.begin();
verify(mRenderer, only()).addObserver(any());
// send first frame - not janky
- setupFirstFrameMockWithDuration(4);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(4, JANK_NONE, 100L);
// send another frame - not janky
- setupOtherFrameMockWithDuration(4);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(4, JANK_NONE, 101L);
// end the trace session, simulate one more valid callback came after the end call.
- when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
- .thenReturn(System.nanoTime());
- setupOtherFrameMockWithDuration(50);
+ when(mChoreographer.getVsyncId()).thenReturn(102L);
mTracker.end();
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(50, JANK_APP_DEADLINE_MISSED, 102L);
- // One more callback with VSYNC after the end() timestamp.
- when(mWrapper.getMetric(FrameMetrics.VSYNC_TIMESTAMP))
- .thenReturn(System.nanoTime());
- setupOtherFrameMockWithDuration(5);
- mTracker.onFrameMetricsAvailable(0);
+ // One more callback with VSYNC after the end() vsync id.
+ sendFrame(4, JANK_NONE, 103L);
verify(mRenderer).removeObserver(any());
@@ -166,20 +231,18 @@
@Test
public void testBeginCancel() {
+ when(mChoreographer.getVsyncId()).thenReturn(100L);
mTracker.begin();
verify(mRenderer).addObserver(any());
// First frame - not janky
- setupFirstFrameMockWithDuration(4);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(4, JANK_NONE, 100L);
// normal frame - not janky
- setupOtherFrameMockWithDuration(12);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(4, JANK_NONE, 101L);
// a janky frame
- setupOtherFrameMockWithDuration(30);
- mTracker.onFrameMetricsAvailable(0);
+ sendFrame(50, JANK_APP_DEADLINE_MISSED, 102L);
mTracker.cancel();
verify(mRenderer).removeObserver(any());
@@ -187,15 +250,26 @@
verify(mTracker, never()).triggerPerfetto();
}
- private void setupFirstFrameMockWithDuration(long durationMillis) {
- doReturn(1L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
- doReturn(TimeUnit.MILLISECONDS.toNanos(durationMillis))
- .when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ private void sendFirstWindowFrame(long durationMillis,
+ @JankType int jankType, long vsyncId) {
+ sendFrame(durationMillis, jankType, vsyncId, true /* firstWindowFrame */);
}
- private void setupOtherFrameMockWithDuration(long durationMillis) {
- doReturn(0L).when(mWrapper).getMetric(FrameMetrics.FIRST_DRAW_FRAME);
+ private void sendFrame(long durationMillis,
+ @JankType int jankType, long vsyncId) {
+ sendFrame(durationMillis, jankType, vsyncId, false /* firstWindowFrame */);
+ }
+
+ private void sendFrame(long durationMillis,
+ @JankType int jankType, long vsyncId, boolean firstWindowFrame) {
+ when(mWrapper.getTiming()).thenReturn(new long[] { 0, vsyncId });
+ doReturn(firstWindowFrame ? 1L : 0L).when(mWrapper)
+ .getMetric(FrameMetrics.FIRST_DRAW_FRAME);
doReturn(TimeUnit.MILLISECONDS.toNanos(durationMillis))
.when(mWrapper).getMetric(FrameMetrics.TOTAL_DURATION);
+ mTracker.onFrameMetricsAvailable(0);
+ mListenerCapture.getValue().onJankDataAvailable(new JankData[] {
+ new JankData(vsyncId, jankType)
+ });
}
}
diff --git a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
index 0ef5643..c4c475b 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -16,6 +16,8 @@
package com.android.internal.jank;
+import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper;
+import static com.android.internal.jank.FrameTracker.ViewRootWrapper;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_TO_STATSD_INTERACTION_TYPE;
@@ -27,6 +29,7 @@
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -85,21 +88,19 @@
public void testBeginEnd() {
// Should return false if the view is not attached.
InteractionJankMonitor monitor = spy(new InteractionJankMonitor(mWorker));
- assertThat(monitor.init(new View(mActivity))).isFalse();
-
- // Verify we init InteractionJankMonitor correctly.
- assertThat(monitor.init(mView)).isTrue();
verify(mWorker).start();
Session session = new Session(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
FrameTracker tracker = spy(new FrameTracker(session, mWorker.getThreadHandler(),
new ThreadedRendererWrapper(mView.getThreadedRenderer()),
+ new ViewRootWrapper(mView.getViewRootImpl()), new SurfaceControlWrapper(),
+ mock(FrameTracker.ChoreographerWrapper.class),
new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
/*traceThresholdFrameTimeMillis=*/ -1));
- doReturn(tracker).when(monitor).createFrameTracker(any());
+ doReturn(tracker).when(monitor).createFrameTracker(any(), any());
// Simulate a trace session and see if begin / end are invoked.
- assertThat(monitor.begin(session.getCuj())).isTrue();
+ assertThat(monitor.begin(mView, session.getCuj())).isTrue();
verify(tracker).begin();
assertThat(monitor.end(session.getCuj())).isTrue();
verify(tracker).end();
@@ -108,7 +109,6 @@
@Test
public void testDisabledThroughDeviceConfig() {
InteractionJankMonitor monitor = new InteractionJankMonitor(mWorker);
- monitor.init(mView);
HashMap<String, String> propertiesValues = new HashMap<>();
propertiesValues.put("enabled", "false");
@@ -116,7 +116,7 @@
DeviceConfig.NAMESPACE_INTERACTION_JANK_MONITOR, propertiesValues);
monitor.getPropertiesChangedListener().onPropertiesChanged(properties);
- assertThat(monitor.begin(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
+ assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
}
@@ -125,14 +125,13 @@
InteractionJankMonitor monitor = new InteractionJankMonitor(mWorker);
// Should return false if invoking begin / end without init invocation.
- assertThat(monitor.begin(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
+ assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
// Everything should be fine if invoking init first.
boolean thrown = false;
try {
- monitor.init(mView);
- assertThat(monitor.begin(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
+ assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
} catch (Exception ex) {
thrown = true;
@@ -146,16 +145,17 @@
InteractionJankMonitor monitor = spy(new InteractionJankMonitor(mWorker));
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
- assertThat(monitor.init(mView)).isTrue();
Session session = new Session(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
FrameTracker tracker = spy(new FrameTracker(session, mWorker.getThreadHandler(),
new ThreadedRendererWrapper(mView.getThreadedRenderer()),
+ new ViewRootWrapper(mView.getViewRootImpl()), new SurfaceControlWrapper(),
+ mock(FrameTracker.ChoreographerWrapper.class),
new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
/*traceThresholdFrameTimeMillis=*/ -1));
- doReturn(tracker).when(monitor).createFrameTracker(any());
+ doReturn(tracker).when(monitor).createFrameTracker(any(), any());
- assertThat(monitor.begin(session.getCuj())).isTrue();
+ assertThat(monitor.begin(mView, session.getCuj())).isTrue();
verify(tracker).begin();
verify(mWorker.getThreadHandler(), atLeastOnce()).sendMessageAtTime(captor.capture(),
anyLong());
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 9531181d..6019b90 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -395,6 +395,16 @@
}
@Override
+ public void addCecSettingChangeListener(String name,
+ IHdmiCecSettingChangeListener listener) {
+ }
+
+ @Override
+ public void removeCecSettingChangeListener(String name,
+ IHdmiCecSettingChangeListener listener) {
+ }
+
+ @Override
public int[] getAllowedCecSettingIntValues(String name) {
return new int[0];
}
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
index f174014..e5000a4 100644
--- a/core/tests/notificationtests/src/android/app/NotificationStressTest.java
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -111,7 +111,7 @@
private void sendNotification(int id, CharSequence text) {
// Fill in arbitrary content
Intent intent = new Intent(Intent.ACTION_VIEW);
- PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
+ PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
CharSequence title = text + " " + id;
CharSequence subtitle = String.valueOf(System.currentTimeMillis());
// Create "typical" notification with random icon
diff --git a/core/tests/overlaytests/device/TEST_MAPPING b/core/tests/overlaytests/device/TEST_MAPPING
deleted file mode 100644
index 43ee00f..0000000
--- a/core/tests/overlaytests/device/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit": [
- {
- "name" : "OverlayDeviceTests"
- }
- ]
-}
diff --git a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
index 4c3eaeb..7175f56 100644
--- a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.util;
+import static android.Manifest.permission.NETWORK_SETTINGS;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -82,6 +84,7 @@
private int mAllowCoarseLocationApps;
private int mFineLocationPermission;
private int mAllowFineLocationApps;
+ private int mNetworkSettingsPermission;
private int mCurrentUser;
private boolean mIsLocationEnabled;
private boolean mThrowSecurityException;
@@ -138,6 +141,7 @@
mFineLocationPermission = PackageManager.PERMISSION_DENIED;
mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED;
mAllowFineLocationApps = AppOpsManager.MODE_ERRORED;
+ mNetworkSettingsPermission = PackageManager.PERMISSION_DENIED;
}
private void setupMockInterface() {
@@ -151,6 +155,8 @@
.thenReturn(mCoarseLocationPermission);
when(mMockContext.checkPermission(mManifestStringFine, -1, mUid))
.thenReturn(mFineLocationPermission);
+ when(mMockContext.checkPermission(NETWORK_SETTINGS, -1, mUid))
+ .thenReturn(mNetworkSettingsPermission);
when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled);
}
@@ -264,6 +270,21 @@
assertEquals(LocationPermissionChecker.ERROR_LOCATION_MODE_OFF, result);
}
+ @Test
+ public void testenforceCanAccessScanResults_LocationModeDisabledHasNetworkSettings()
+ throws Exception {
+ mThrowSecurityException = false;
+ mIsLocationEnabled = false;
+ mNetworkSettingsPermission = PackageManager.PERMISSION_GRANTED;
+ setupTestCase();
+
+ final int result =
+ mChecker.checkLocationPermissionWithDetailInfo(
+ TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
+ assertEquals(LocationPermissionChecker.SUCCEEDED, result);
+ }
+
+
private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
try {
r.run();
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index fb8b17c..201f649 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -102,6 +102,14 @@
}
prebuilt_etc {
+ name: "privapp_whitelist_com.android.imsserviceentitlement",
+ product_specific: true,
+ sub_dir: "permissions",
+ src: "com.android.imsserviceentitlement.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
name: "privapp_whitelist_com.android.launcher3",
system_ext_specific: true,
sub_dir: "permissions",
diff --git a/data/etc/com.android.imsserviceentitlement.xml b/data/etc/com.android.imsserviceentitlement.xml
new file mode 100644
index 0000000..4fd91c3
--- /dev/null
+++ b/data/etc/com.android.imsserviceentitlement.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<permissions>
+ <privapp-permissions package="com.android.imsserviceentitlement">
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ <permission name="android.permission.MODIFY_PHONE_STATE"/>
+ </privapp-permissions>
+</permissions>
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 73fff72..af100c9 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -31,6 +31,7 @@
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
/**
@@ -50,19 +51,21 @@
* Parse the fonts.xml
*/
public static FontConfig parse(InputStream in, String fontDir,
- @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
+ @Nullable Map<String, File> updatableFontMap)
+ throws XmlPullParserException, IOException {
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(in, null);
parser.nextTag();
- return readFamilies(parser, fontDir, updatableFontDir);
+ return readFamilies(parser, fontDir, updatableFontMap);
} finally {
in.close();
}
}
private static FontConfig readFamilies(XmlPullParser parser, String fontDir,
- @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
+ @Nullable Map<String, File> updatableFontMap)
+ throws XmlPullParserException, IOException {
List<FontConfig.Family> families = new ArrayList<>();
List<FontConfig.Alias> aliases = new ArrayList<>();
@@ -71,7 +74,7 @@
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
String tag = parser.getName();
if (tag.equals("family")) {
- families.add(readFamily(parser, fontDir, updatableFontDir));
+ families.add(readFamily(parser, fontDir, updatableFontMap));
} else if (tag.equals("alias")) {
aliases.add(readAlias(parser));
} else {
@@ -86,7 +89,8 @@
* Reads a family element
*/
public static FontConfig.Family readFamily(XmlPullParser parser, String fontDir,
- @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
+ @Nullable Map<String, File> updatableFontMap)
+ throws XmlPullParserException, IOException {
final String name = parser.getAttributeValue(null, "name");
final String lang = parser.getAttributeValue("", "lang");
final String variant = parser.getAttributeValue(null, "variant");
@@ -95,7 +99,7 @@
if (parser.getEventType() != XmlPullParser.START_TAG) continue;
final String tag = parser.getName();
if (tag.equals("font")) {
- fonts.add(readFont(parser, fontDir, updatableFontDir));
+ fonts.add(readFont(parser, fontDir, updatableFontMap));
} else {
skip(parser);
}
@@ -117,7 +121,8 @@
Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");
private static FontConfig.Font readFont(XmlPullParser parser, String fontDir,
- @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
+ @Nullable Map<String, File> updatableFontMap)
+ throws XmlPullParserException, IOException {
String indexStr = parser.getAttributeValue(null, "index");
int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
List<FontVariationAxis> axes = new ArrayList<FontVariationAxis>();
@@ -139,20 +144,20 @@
}
}
String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
- String fontName = findFontFile(sanitizedName, fontDir, updatableFontDir);
+ String fontName = findFontFile(sanitizedName, fontDir, updatableFontMap);
return new FontConfig.Font(fontName, index, axes.toArray(
new FontVariationAxis[axes.size()]), weight, isItalic, fallbackFor);
}
- private static String findFontFile(String fileName, String fontDir,
- @Nullable String updatableFontDir) {
- if (updatableFontDir != null) {
- String updatableFontName = updatableFontDir + fileName;
- if (new File(updatableFontName).exists()) {
- return updatableFontName;
+ private static String findFontFile(String name, String fontDir,
+ @Nullable Map<String, File> updatableFontMap) {
+ if (updatableFontMap != null) {
+ File updatedFile = updatableFontMap.get(name);
+ if (updatedFile != null) {
+ return updatedFile.getAbsolutePath();
}
}
- return fontDir + fileName;
+ return fontDir + name;
}
private static FontVariationAxis readAxis(XmlPullParser parser)
diff --git a/graphics/java/android/graphics/Point.java b/graphics/java/android/graphics/Point.java
index 61a4749..cf2f970 100644
--- a/graphics/java/android/graphics/Point.java
+++ b/graphics/java/android/graphics/Point.java
@@ -20,8 +20,6 @@
import android.os.Parcel;
import android.os.Parcelable;
-import java.io.PrintWriter;
-
/**
* Point holds two integer coordinates
*/
@@ -72,17 +70,6 @@
return this.x == x && this.y == y;
}
- /**
- * Dumps a human-readable shortened string of the point into the given
- * stream
- *
- * @param pw The {@link PrintWriter} into which the string representation of
- * the point will be written.
- */
- public final void dump(@NonNull PrintWriter pw) {
- pw.print("["); pw.print(x); pw.print(","); pw.print(y); pw.print("]");
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index 49888fd..8dd7f31 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -71,8 +71,8 @@
}
/*package*/
- long finishRecording() {
- return nFinishRecording(mNativeCanvasWrapper);
+ void finishRecording(RenderNode node) {
+ nFinishRecording(mNativeCanvasWrapper, node.mNativeRenderNode);
}
///////////////////////////////////////////////////////////////////////////
@@ -220,7 +220,7 @@
CanvasProperty<Float> progress, RuntimeShader shader) {
nDrawRipple(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
radius.getNativeContainer(), paint.getNativeContainer(),
- progress.getNativeContainer(), shader.getNativeShaderFactory());
+ progress.getNativeContainer(), shader.getNativeShaderBuilder());
}
/**
@@ -271,7 +271,7 @@
@CriticalNative
private static native void nEnableZ(long renderer, boolean enableZ);
@CriticalNative
- private static native long nFinishRecording(long renderer);
+ private static native void nFinishRecording(long renderer, long renderNode);
@CriticalNative
private static native void nDrawRenderNode(long renderer, long renderNode);
@CriticalNative
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 117828d..c1310a9 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -30,7 +30,6 @@
import com.android.internal.util.ArrayUtils;
import dalvik.annotation.optimization.CriticalNative;
-import dalvik.annotation.optimization.FastNative;
import libcore.util.NativeAllocationRegistry;
@@ -406,8 +405,7 @@
}
RecordingCanvas canvas = mCurrentRecordingCanvas;
mCurrentRecordingCanvas = null;
- long displayList = canvas.finishRecording();
- nSetDisplayList(mNativeRenderNode, displayList);
+ canvas.finishRecording(this);
canvas.recycle();
}
@@ -438,7 +436,7 @@
* obsolete resources after related resources are gone.
*/
public void discardDisplayList() {
- nSetDisplayList(mNativeRenderNode, 0);
+ nDiscardDisplayList(mNativeRenderNode);
}
/**
@@ -1528,20 +1526,14 @@
private static native void nEndAllAnimators(long renderNode);
-
- ///////////////////////////////////////////////////////////////////////////
- // @FastNative methods
- ///////////////////////////////////////////////////////////////////////////
-
- @FastNative
- private static native void nSetDisplayList(long renderNode, long newData);
-
-
///////////////////////////////////////////////////////////////////////////
// @CriticalNative methods
///////////////////////////////////////////////////////////////////////////
@CriticalNative
+ private static native void nDiscardDisplayList(long renderNode);
+
+ @CriticalNative
private static native boolean nIsValid(long renderNode);
// Matrix
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index 7f2e503..1ace322 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -17,7 +17,6 @@
package android.graphics;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import libcore.util.NativeAllocationRegistry;
@@ -33,14 +32,12 @@
RuntimeShader.class.getClassLoader(), nativeGetFinalizer());
}
- private byte[] mUniforms;
- private Shader[] mInputShaders;
private boolean mIsOpaque;
/**
- * Current native shader factory instance.
+ * Current native shader builder instance.
*/
- private long mNativeInstanceRuntimeShaderFactory;
+ private long mNativeInstanceRuntimeShaderBuilder;
/**
* Creates a new RuntimeShader.
@@ -50,80 +47,86 @@
* on number of uniforms declared by sksl.
* @param isOpaque True if all pixels have alpha 1.0f.
*/
- public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms, boolean isOpaque) {
- this(sksl, uniforms, null, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
- }
-
- /**
- * Creates a new RuntimeShader.
- *
- * @param sksl The text of SKSL program to run on the GPU.
- * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
- * on number of uniforms declared by sksl.
- * @param shaderInputs Array of shaders passed to the SKSL shader. Array size depends
- * on the number of input shaders declared in the sksl
- * @param isOpaque True if all pixels have alpha 1.0f.
- */
- public RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms,
- @Nullable Shader[] shaderInputs, boolean isOpaque) {
- this(sksl, uniforms, shaderInputs, isOpaque, ColorSpace.get(ColorSpace.Named.SRGB));
- }
-
- private RuntimeShader(@NonNull String sksl, @Nullable byte[] uniforms,
- @Nullable Shader[] shaderInputs, boolean isOpaque,
- ColorSpace colorSpace) {
- super(colorSpace);
- mUniforms = uniforms;
- mInputShaders = shaderInputs;
+ public RuntimeShader(@NonNull String sksl, boolean isOpaque) {
+ super(ColorSpace.get(ColorSpace.Named.SRGB));
mIsOpaque = isOpaque;
- mNativeInstanceRuntimeShaderFactory = nativeCreateShaderFactory(sksl);
- NoImagePreloadHolder.sRegistry.registerNativeAllocation(this,
- mNativeInstanceRuntimeShaderFactory);
+ mNativeInstanceRuntimeShaderBuilder = nativeCreateBuilder(sksl);
+ NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+ this, mNativeInstanceRuntimeShaderBuilder);
}
/**
- * Sets new value for shader parameters.
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than float then an
+ * IllegalArgumentException is thrown.
*
- * @param uniforms Array of parameters passed by the SKSL shader. Array size depends
- * on number of uniforms declared by mSksl.
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param value
*/
- public void updateUniforms(@Nullable byte[] uniforms) {
- mUniforms = uniforms;
+ public void setUniform(@NonNull String uniformName, float value) {
+ setUniform(uniformName, new float[] {value});
+ }
+
+ /**
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than float2/vec2 then an
+ * IllegalArgumentException is thrown.
+ *
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param value1
+ * @param value2
+ */
+ public void setUniform(@NonNull String uniformName, float value1, float value2) {
+ setUniform(uniformName, new float[] {value1, value2});
+ }
+
+ /**
+ * Sets the uniform value corresponding to this shader. If the shader does not have a uniform
+ * with that name or if the uniform is declared with a type other than a vecN/floatN where N is
+ * the size of the values array then an IllegalArgumentException is thrown.
+ *
+ * @param uniformName name matching the uniform declared in the SKSL shader
+ * @param values
+ */
+ public void setUniform(@NonNull String uniformName, float[] values) {
+ nativeUpdateUniforms(mNativeInstanceRuntimeShaderBuilder, uniformName, values);
discardNativeInstance();
}
/**
- * Sets new values for the shaders that serve as inputs to this shader.
+ * Sets the uniform shader that is declares as input to this shader. If the shader does not
+ * have a uniform shader with that name then an IllegalArgumentException is thrown.
*
- * @param shaderInputs Array of Shaders passed into the SKSL shader. Array size depends
- * on number of input shaders declared by sksl.
+ * @param shaderName name matching the uniform declared in the SKSL shader
+ * @param shader shader passed into the SKSL shader for sampling
*/
- public void updateInputShaders(@Nullable Shader[] shaderInputs) {
- mInputShaders = shaderInputs;
+ public void setInputShader(@NonNull String shaderName, @NonNull Shader shader) {
+ nativeUpdateShader(
+ mNativeInstanceRuntimeShaderBuilder, shaderName, shader.getNativeInstance());
discardNativeInstance();
}
/** @hide */
@Override
protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
- long[] nativeShaders = mInputShaders.length > 0 ? new long[mInputShaders.length] : null;
- for (int i = 0; i < mInputShaders.length; i++) {
- nativeShaders[i] = mInputShaders[i].getNativeInstance(filterFromPaint);
- }
-
- return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
- nativeShaders, colorSpace().getNativeInstance(), mIsOpaque);
+ return nativeCreateShader(mNativeInstanceRuntimeShaderBuilder, nativeMatrix, mIsOpaque);
}
- public long getNativeShaderFactory() {
- return mNativeInstanceRuntimeShaderFactory;
+ public long getNativeShaderBuilder() {
+ return mNativeInstanceRuntimeShaderBuilder;
}
- private static native long nativeCreate(long shaderFactory, long matrix, byte[] inputs,
- long[] shaderInputs, long colorSpaceHandle, boolean isOpaque);
-
- private static native long nativeCreateShaderFactory(String sksl);
+ public boolean isOpaque() {
+ return mIsOpaque;
+ }
private static native long nativeGetFinalizer();
+ private static native long nativeCreateBuilder(String sksl);
+ private static native long nativeCreateShader(
+ long shaderBuilder, long matrix, boolean isOpaque);
+ private static native void nativeUpdateUniforms(
+ long shaderBuilder, String uniformName, float[] uniforms);
+ private static native void nativeUpdateShader(
+ long shaderBuilder, String shaderName, long shader);
}
diff --git a/graphics/java/android/graphics/fonts/FontFileUtil.java b/graphics/java/android/graphics/fonts/FontFileUtil.java
index f8b456b..2896c46 100644
--- a/graphics/java/android/graphics/fonts/FontFileUtil.java
+++ b/graphics/java/android/graphics/fonts/FontFileUtil.java
@@ -20,6 +20,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import dalvik.annotation.optimization.FastNative;
+
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -131,4 +133,44 @@
buffer.order(originalOrder);
}
}
+
+ /**
+ * Analyze head OpenType table and return fontRevision value as 32bit integer.
+ *
+ * The font revision is stored in 16.16 bit fixed point value. This function returns this fixed
+ * point value as 32 bit integer, i.e. the value multiplied with 65536.
+ *
+ * IllegalArgumentException will be thrown for invalid font data.
+ * If the font file is invalid, returns -1L.
+ *
+ * @param buffer a buffer of OpenType font
+ * @param index a font index
+ * @return font revision that shifted 16 bits left.
+ */
+ public static long getRevision(@NonNull ByteBuffer buffer, @IntRange(from = 0) int index) {
+ return nGetFontRevision(buffer, index);
+ }
+
+ /**
+ * Analyze name OpenType table and return PostScript name.
+ *
+ * IllegalArgumentException will be thrown for invalid font data.
+ * null will be returned if not found or the PostScript name is invalid.
+ *
+ * @param buffer a buffer of OpenType font
+ * @param index a font index
+ * @return a post script name or null if it is invalid or not found.
+ */
+ public static String getPostScriptName(@NonNull ByteBuffer buffer,
+ @IntRange(from = 0) int index) {
+ return nGetFontPostScriptName(buffer, index);
+ }
+
+ @FastNative
+ private static native long nGetFontRevision(@NonNull ByteBuffer buffer,
+ @IntRange(from = 0) int index);
+
+ @FastNative
+ private static native String nGetFontPostScriptName(@NonNull ByteBuffer buffer,
+ @IntRange(from = 0) int index);
}
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 16a53c2..93b1fcc 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -92,7 +92,7 @@
readFontCustomization("/product/etc/fonts_customization.xml", "/product/fonts/");
Map<String, FontFamily[]> map = new ArrayMap<>();
// TODO: use updated fonts
- buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", null /* updatableFontDir */,
+ buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", null /* updatableFontMap */,
oemCustomization, map);
Set<Font> res = new HashSet<>();
for (FontFamily[] families : map.values()) {
@@ -228,7 +228,7 @@
}
/**
- * @see #buildSystemFallback(String, String, String, FontCustomizationParser.Result, Map)
+ * @see #buildSystemFallback(String, String, Map, FontCustomizationParser.Result, Map)
* @hide
*/
@VisibleForTesting
@@ -236,7 +236,7 @@
@NonNull String fontDir,
@NonNull FontCustomizationParser.Result oemCustomization,
@NonNull Map<String, FontFamily[]> fallbackMap) {
- return buildSystemFallback(xmlPath, fontDir, null /* updatableFontDir */,
+ return buildSystemFallback(xmlPath, fontDir, null /* updatableFontMap */,
oemCustomization, fallbackMap);
}
@@ -246,8 +246,7 @@
* @param xmlPath A full path string to the fonts.xml file.
* @param fontDir A full path string to the system font directory. This must end with
* slash('/').
- * @param updatableFontDir A full path string to the updatable system font directory. This
- * must end with slash('/').
+ * @param updatableFontMap A map from font file name to updated font file path.
* @param fallbackMap An output system fallback map. Caller must pass empty map.
* @return a list of aliases
* @hide
@@ -255,12 +254,12 @@
@VisibleForTesting
public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
@NonNull String fontDir,
- @Nullable String updatableFontDir,
+ @Nullable Map<String, File> updatableFontMap,
@NonNull FontCustomizationParser.Result oemCustomization,
@NonNull Map<String, FontFamily[]> fallbackMap) {
try {
final FileInputStream fontsIn = new FileInputStream(xmlPath);
- final FontConfig fontConfig = FontListParser.parse(fontsIn, fontDir, updatableFontDir);
+ final FontConfig fontConfig = FontListParser.parse(fontsIn, fontDir, updatableFontMap);
final HashMap<String, ByteBuffer> bufferCache = new HashMap<String, ByteBuffer>();
final FontConfig.Family[] xmlFamilies = fontConfig.getFamilies();
@@ -329,12 +328,12 @@
/** @hide */
public static Pair<FontConfig.Alias[], Map<String, FontFamily[]>>
- initializeSystemFonts(@Nullable String updatableFontDir) {
+ initializeSystemFonts(@Nullable Map<String, File> updatableFontMap) {
final FontCustomizationParser.Result oemCustomization =
readFontCustomization("/product/etc/fonts_customization.xml", "/product/fonts/");
Map<String, FontFamily[]> map = new ArrayMap<>();
FontConfig.Alias[] aliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
- updatableFontDir, oemCustomization, map);
+ updatableFontMap, oemCustomization, map);
synchronized (LOCK) {
sFamilyMap = map;
}
diff --git a/keystore/java/android/security/AuthTokenUtils.java b/keystore/java/android/security/AuthTokenUtils.java
new file mode 100644
index 0000000..14d6626
--- /dev/null
+++ b/keystore/java/android/security/AuthTokenUtils.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.annotation.NonNull;
+import android.hardware.security.keymint.HardwareAuthToken;
+import android.hardware.security.keymint.Timestamp;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * @hide This Utils class provides method(s) for AuthToken conversion.
+ */
+public class AuthTokenUtils {
+
+ private AuthTokenUtils(){
+ }
+
+ /**
+ * Build a HardwareAuthToken from a byte array
+ * @param array byte array representing an auth token
+ * @return HardwareAuthToken representation of an auth token
+ */
+ public static @NonNull HardwareAuthToken toHardwareAuthToken(@NonNull byte[] array) {
+ final HardwareAuthToken hardwareAuthToken = new HardwareAuthToken();
+
+ // First byte is version, which does not exist in HardwareAuthToken anymore
+ // Next 8 bytes is the challenge.
+ hardwareAuthToken.challenge =
+ ByteBuffer.wrap(array, 1, 8).order(ByteOrder.nativeOrder()).getLong();
+
+ // Next 8 bytes is the userId
+ hardwareAuthToken.userId =
+ ByteBuffer.wrap(array, 9, 8).order(ByteOrder.nativeOrder()).getLong();
+
+ // Next 8 bytes is the authenticatorId.
+ hardwareAuthToken.authenticatorId =
+ ByteBuffer.wrap(array, 17, 8).order(ByteOrder.nativeOrder()).getLong();
+
+ // while the other fields are in machine byte order, authenticatorType and timestamp
+ // are in network byte order.
+ // Next 4 bytes is the authenticatorType.
+ hardwareAuthToken.authenticatorType =
+ ByteBuffer.wrap(array, 25, 4).order(ByteOrder.BIG_ENDIAN).getInt();
+ // Next 8 bytes is the timestamp.
+ final Timestamp timestamp = new Timestamp();
+ timestamp.milliSeconds =
+ ByteBuffer.wrap(array, 29, 8).order(ByteOrder.BIG_ENDIAN).getLong();
+ hardwareAuthToken.timestamp = timestamp;
+
+ // Last 32 bytes is the mac, 37:69
+ hardwareAuthToken.mac = new byte[32];
+ System.arraycopy(array, 37 /* srcPos */,
+ hardwareAuthToken.mac,
+ 0 /* destPos */,
+ 32 /* length */);
+
+ return hardwareAuthToken;
+ }
+}
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java
new file mode 100644
index 0000000..2b76f25
--- /dev/null
+++ b/keystore/java/android/security/Authorization.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.annotation.NonNull;
+import android.hardware.security.keymint.HardwareAuthToken;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.security.authorization.IKeystoreAuthorization;
+import android.system.keystore2.ResponseCode;
+import android.util.Log;
+
+/**
+ * @hide This is the client side for IKeystoreAuthorization AIDL.
+ * It shall only be used by biometric authentication providers and Gatekeeper.
+ */
+public class Authorization {
+ private static final String TAG = "KeystoreAuthorization";
+ private static IKeystoreAuthorization sIKeystoreAuthorization;
+
+ public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
+
+ public Authorization() {
+ sIKeystoreAuthorization = null;
+ }
+
+ private static synchronized IKeystoreAuthorization getService() {
+ if (sIKeystoreAuthorization == null) {
+ sIKeystoreAuthorization = IKeystoreAuthorization.Stub.asInterface(
+ ServiceManager.getService("android.security.authorization"));
+ }
+ return sIKeystoreAuthorization;
+ }
+
+ /**
+ * Adds an auth token to keystore2.
+ *
+ * @param authToken created by Android authenticators.
+ * @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}.
+ */
+ public int addAuthToken(@NonNull HardwareAuthToken authToken) {
+ if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
+ try {
+ getService().addAuthToken(authToken);
+ return 0;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Can not connect to keystore", e);
+ return SYSTEM_ERROR;
+ } catch (ServiceSpecificException e) {
+ return e.errorCode;
+ }
+ }
+
+ /**
+ * Add an auth token to Keystore 2.0 in the legacy serialized auth token format.
+ * @param authToken
+ * @return 0 if successful or a {@code ResponseCode}.
+ */
+ public int addAuthToken(@NonNull byte[] authToken) {
+ return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken));
+ }
+
+}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index c70c986..4a67135 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -996,6 +996,7 @@
*/
public int addAuthToken(byte[] authToken) {
try {
+ new Authorization().addAuthToken(authToken);
return mBinder.addAuthToken(authToken);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
diff --git a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
index 6c733ba..33e8ded 100644
--- a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
@@ -139,7 +139,9 @@
int inputConsumed = ArrayUtils.copy(input, inputOffset, mChunk, mChunkLength,
inputLength);
inputLength -= inputConsumed;
- inputOffset += inputOffset;
+ inputOffset += inputConsumed;
+ mChunkLength += inputConsumed;
+ if (mChunkLength < mChunkSizeMax) return output;
byte[] o = mKeyStoreStream.update(mChunk);
if (o != null) {
output = ArrayUtils.concat(output, o);
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index 0290d9f..2cfb13e 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,6 +1,12 @@
{
"version": "1.0.0",
"messages": {
+ "-2076257741": {
+ "message": "Transition requested: %s %s",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TRANSITIONS",
+ "at": "com\/android\/wm\/shell\/transition\/Transitions.java"
+ },
"-1683614271": {
"message": "Existing task: id=%d component=%s",
"level": "VERBOSE",
@@ -133,12 +139,6 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
- "846958769": {
- "message": "Transition requested: type=%d %s",
- "level": "VERBOSE",
- "group": "WM_SHELL_TRANSITIONS",
- "at": "com\/android\/wm\/shell\/transition\/Transitions.java"
- },
"900599280": {
"message": "Can't pair unresizeable tasks task1.isResizeable=%b task1.isResizeable=%b",
"level": "ERROR",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
index 0146b72..7aedc1b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -71,6 +71,7 @@
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
final Point positionInParent = taskInfo.positionInParent;
mSyncQueue.runInSync(t -> t.setPosition(leash, positionInParent.x, positionInParent.y));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
index 4ef489f..cb54021 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
@@ -111,6 +111,7 @@
}
mDisplayAreasInfo.put(displayId, displayAreaInfo);
+ mLeashes.put(displayId, leash);
ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
if (listeners != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
index f213af7..52648d9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
@@ -16,7 +16,7 @@
package com.android.wm.shell;
-import android.util.Slog;
+import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.ShellExecutor;
@@ -24,10 +24,10 @@
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.PrintWriter;
import java.util.Optional;
-import java.util.concurrent.TimeUnit;
/**
* An entry point into the shell for dumping shell internal state and running adb commands.
@@ -38,6 +38,7 @@
private static final String TAG = ShellCommandHandlerImpl.class.getSimpleName();
private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
+ private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<Pip> mPipOptional;
private final Optional<OneHanded> mOneHandedOptional;
private final Optional<HideDisplayCutout> mHideDisplayCutout;
@@ -49,19 +50,21 @@
public static ShellCommandHandler create(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
+ Optional<SplitScreen> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
Optional<AppPairs> appPairsOptional,
ShellExecutor mainExecutor) {
return new ShellCommandHandlerImpl(shellTaskOrganizer, legacySplitScreenOptional,
- pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional,
- mainExecutor).mImpl;
+ splitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
+ appPairsOptional, mainExecutor).mImpl;
}
private ShellCommandHandlerImpl(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
+ Optional<SplitScreen> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
@@ -69,6 +72,7 @@
ShellExecutor mainExecutor) {
mShellTaskOrganizer = shellTaskOrganizer;
mLegacySplitScreenOptional = legacySplitScreenOptional;
+ mSplitScreenOptional = splitScreenOptional;
mPipOptional = pipOptional;
mOneHandedOptional = oneHandedOptional;
mHideDisplayCutout = hideDisplayCutout;
@@ -88,6 +92,9 @@
pw.println();
pw.println();
mAppPairsOptional.ifPresent(appPairs -> appPairs.dump(pw, ""));
+ pw.println();
+ pw.println();
+ mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw, ""));
}
@@ -102,6 +109,14 @@
return runPair(args, pw);
case "unpair":
return runUnpair(args, pw);
+ case "moveToSideStage":
+ return runMoveToSideStage(args, pw);
+ case "removeFromSideStage":
+ return runRemoveFromSideStage(args, pw);
+ case "setSideStagePosition":
+ return runSetSideStagePosition(args, pw);
+ case "setSideStageVisibility":
+ return runSetSideStageVisibility(args, pw);
case "help":
return runHelp(pw);
default:
@@ -109,7 +124,6 @@
}
}
-
private boolean runPair(String[] args, PrintWriter pw) {
if (args.length < 4) {
// First two arguments are "WMShell" and command name.
@@ -133,6 +147,53 @@
return true;
}
+ private boolean runMoveToSideStage(String[] args, PrintWriter pw) {
+ if (args.length < 3) {
+ // First arguments are "WMShell" and command name.
+ pw.println("Error: task id should be provided as arguments");
+ return false;
+ }
+ final int taskId = new Integer(args[2]);
+ final int sideStagePosition = args.length > 3
+ ? new Integer(args[3]) : SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
+ mSplitScreenOptional.ifPresent(split -> split.moveToSideStage(taskId, sideStagePosition));
+ return true;
+ }
+
+ private boolean runRemoveFromSideStage(String[] args, PrintWriter pw) {
+ if (args.length < 3) {
+ // First arguments are "WMShell" and command name.
+ pw.println("Error: task id should be provided as arguments");
+ return false;
+ }
+ final int taskId = new Integer(args[2]);
+ mSplitScreenOptional.ifPresent(split -> split.removeFromSideStage(taskId));
+ return true;
+ }
+
+ private boolean runSetSideStagePosition(String[] args, PrintWriter pw) {
+ if (args.length < 3) {
+ // First arguments are "WMShell" and command name.
+ pw.println("Error: side stage position should be provided as arguments");
+ return false;
+ }
+ final int position = new Integer(args[2]);
+ mSplitScreenOptional.ifPresent(split -> split.setSideStagePosition(position));
+ return true;
+ }
+
+ private boolean runSetSideStageVisibility(String[] args, PrintWriter pw) {
+ if (args.length < 3) {
+ // First arguments are "WMShell" and command name.
+ pw.println("Error: side stage position should be provided as arguments");
+ return false;
+ }
+ final Boolean visible = new Boolean(args[2]);
+
+ mSplitScreenOptional.ifPresent(split -> split.setSideStageVisibility(visible));
+ return true;
+ }
+
private boolean runHelp(PrintWriter pw) {
pw.println("Window Manager Shell commands:");
pw.println(" help");
@@ -142,6 +203,14 @@
pw.println(" pair <taskId1> <taskId2>");
pw.println(" unpair <taskId>");
pw.println(" Pairs/unpairs tasks with given ids.");
+ pw.println(" moveToSideStage <taskId> <SideStagePosition>");
+ pw.println(" Move a task with given id in split-screen mode.");
+ pw.println(" removeFromSideStage <taskId>");
+ pw.println(" Remove a task with given id in split-screen mode.");
+ pw.println(" setSideStagePosition <SideStagePosition>");
+ pw.println(" Sets the position of the side-stage.");
+ pw.println(" setSideStageVisibility <true/false>");
+ pw.println(" Show/hide side-stage.");
return true;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index 0cee0a2..b43203d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -24,6 +24,7 @@
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -38,6 +39,7 @@
private final DragAndDropController mDragAndDropController;
private final ShellTaskOrganizer mShellTaskOrganizer;
private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
+ private final Optional<SplitScreen> mSplitScreenOptional;
private final Optional<AppPairs> mAppPairsOptional;
private final FullscreenTaskListener mFullscreenTaskListener;
private final ShellExecutor mMainExecutor;
@@ -49,6 +51,7 @@
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
+ Optional<SplitScreen> splitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
@@ -57,6 +60,7 @@
dragAndDropController,
shellTaskOrganizer,
legacySplitScreenOptional,
+ splitScreenOptional,
appPairsOptional,
fullscreenTaskListener,
transitions,
@@ -67,6 +71,7 @@
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
+ Optional<SplitScreen> splitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
@@ -75,6 +80,7 @@
mDragAndDropController = dragAndDropController;
mShellTaskOrganizer = shellTaskOrganizer;
mLegacySplitScreenOptional = legacySplitScreenOptional;
+ mSplitScreenOptional = splitScreenOptional;
mAppPairsOptional = appPairsOptional;
mFullscreenTaskListener = fullscreenTaskListener;
mTransitions = transitions;
@@ -91,6 +97,7 @@
mShellTaskOrganizer.registerOrganizer();
mAppPairsOptional.ifPresent(AppPairs::onOrganizerRegistered);
+ mSplitScreenOptional.ifPresent(SplitScreen::onOrganizerRegistered);
// Bind the splitscreen impl to the drag drop controller
mDragAndDropController.initialize(mLegacySplitScreenOptional);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index 563de06..bab5140 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -94,7 +94,7 @@
mTaskInfo1 = task1;
mTaskInfo2 = task2;
- mSplitLayout = new SplitLayout(
+ mSplitLayout = new SplitLayout(TAG + "SplitDivider",
mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
mRootTaskInfo.configuration, this /* layoutChangeListener */,
b -> b.setParent(mRootTaskLeash));
@@ -248,13 +248,13 @@
final Rect bounds1 = layout.getBounds1();
final Rect bounds2 = layout.getBounds2();
mSyncQueue.runInSync(t -> t
- // Ignores the original surface bounds so that the app could fill up the gap
- // between each surface with corresponding background while resizing.
- .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height())
- .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height())
.setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
.setPosition(mTaskLeash1, bounds1.left, bounds1.top)
- .setPosition(mTaskLeash2, bounds2.left, bounds2.top));
+ .setPosition(mTaskLeash2, bounds2.left, bounds2.top)
+ // Sets crop to prevent visible region of tasks overlap with each other when
+ // re-positioning surfaces while resizing.
+ .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height())
+ .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height()));
}
@Override
@@ -271,10 +271,11 @@
mSyncQueue.runInSync(t -> t
// Resets layer of divider bar to make sure it is always on top.
.setLayer(dividerLeash, Integer.MAX_VALUE)
- .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height())
- .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height())
.setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
.setPosition(mTaskLeash1, bounds1.left, bounds1.top)
- .setPosition(mTaskLeash2, bounds2.left, bounds2.top));
+ .setPosition(mTaskLeash2, bounds2.left, bounds2.top)
+ // Resets crop to apply new surface bounds directly.
+ .setWindowCrop(mTaskLeash1, null)
+ .setWindowCrop(mTaskLeash2, null));
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
index f2f0982..e380426 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java
@@ -19,41 +19,58 @@
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
import android.app.ActivityManager;
+import android.util.Slog;
import android.util.SparseArray;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import java.io.PrintWriter;
+import java.util.concurrent.TimeUnit;
/**
* Class manages app-pairs multitasking mode and implements the main interface {@link AppPairs}.
*/
-public class AppPairsController implements AppPairs {
+public class AppPairsController {
private static final String TAG = AppPairsController.class.getSimpleName();
private final ShellTaskOrganizer mTaskOrganizer;
private final SyncTransactionQueue mSyncQueue;
+ private final ShellExecutor mMainExecutor;
+ private final AppPairsImpl mImpl = new AppPairsImpl();
private AppPairsPool mPairsPool;
// Active app-pairs mapped by root task id key.
private final SparseArray<AppPair> mActiveAppPairs = new SparseArray<>();
private final DisplayController mDisplayController;
- public AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
- DisplayController displayController) {
+ /**
+ * Creates {@link AppPairs}, returns {@code null} if the feature is not supported.
+ */
+ @Nullable
+ public static AppPairs create(ShellTaskOrganizer organizer,
+ SyncTransactionQueue syncQueue, DisplayController displayController,
+ ShellExecutor mainExecutor) {
+ return new AppPairsController(organizer, syncQueue, displayController,
+ mainExecutor).mImpl;
+ }
+
+ AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
+ DisplayController displayController, ShellExecutor mainExecutor) {
mTaskOrganizer = organizer;
mSyncQueue = syncQueue;
mDisplayController = displayController;
+ mMainExecutor = mainExecutor;
}
- @Override
- public void onOrganizerRegistered() {
+ void onOrganizerRegistered() {
if (mPairsPool == null) {
setPairsPool(new AppPairsPool(this));
}
@@ -64,8 +81,7 @@
mPairsPool = pool;
}
- @Override
- public boolean pair(int taskId1, int taskId2) {
+ boolean pair(int taskId1, int taskId2) {
final ActivityManager.RunningTaskInfo task1 = mTaskOrganizer.getRunningTaskInfo(taskId1);
final ActivityManager.RunningTaskInfo task2 = mTaskOrganizer.getRunningTaskInfo(taskId2);
if (task1 == null || task2 == null) {
@@ -74,8 +90,7 @@
return pair(task1, task2);
}
- @Override
- public boolean pair(ActivityManager.RunningTaskInfo task1,
+ boolean pair(ActivityManager.RunningTaskInfo task1,
ActivityManager.RunningTaskInfo task2) {
return pairInner(task1, task2) != null;
}
@@ -94,8 +109,7 @@
return pair;
}
- @Override
- public void unpair(int taskId) {
+ void unpair(int taskId) {
unpair(taskId, true /* releaseToPool */);
}
@@ -135,8 +149,7 @@
return mDisplayController;
}
- @Override
- public void dump(@NonNull PrintWriter pw, String prefix) {
+ private void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
final String childPrefix = innerPrefix + " ";
pw.println(prefix + this);
@@ -155,4 +168,55 @@
return TAG + "#" + mActiveAppPairs.size();
}
+ private class AppPairsImpl implements AppPairs {
+ @Override
+ public boolean pair(int task1, int task2) {
+ boolean[] result = new boolean[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = AppPairsController.this.pair(task1, task2);
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
+ }
+ return result[0];
+ }
+
+ @Override
+ public boolean pair(ActivityManager.RunningTaskInfo task1,
+ ActivityManager.RunningTaskInfo task2) {
+ boolean[] result = new boolean[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = AppPairsController.this.pair(task1, task2);
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
+ }
+ return result[0];
+ }
+
+ @Override
+ public void unpair(int taskId) {
+ mMainExecutor.execute(() -> {
+ AppPairsController.this.unpair(taskId);
+ });
+ }
+
+ @Override
+ public void onOrganizerRegistered() {
+ mMainExecutor.execute(() -> {
+ AppPairsController.this.onOrganizerRegistered();
+ });
+ }
+
+ @Override
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ try {
+ mMainExecutor.executeBlocking(() -> AppPairsController.this.dump(pw, prefix));
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to dump AppPairsController in 2s");
+ }
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 707747b..e17a943 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.util.AttributeSet;
+import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceControlViewHost;
import android.view.VelocityTracker;
@@ -54,6 +55,7 @@
private VelocityTracker mVelocityTracker;
private boolean mMoving;
private int mStartPos;
+ private GestureDetector mDoubleTapDetector;
public DividerView(@NonNull Context context) {
super(context);
@@ -88,6 +90,7 @@
mBackground = findViewById(R.id.docked_divider_background);
mTouchElevation = getResources().getDimensionPixelSize(
R.dimen.docked_stack_divider_lift_elevation);
+ mDoubleTapDetector = new GestureDetector(getContext(), new DoubleTapListener());
setOnTouchListener(this);
}
@@ -136,6 +139,8 @@
mSplitLayout.snapToTarget(position, snapTarget);
break;
}
+
+ mDoubleTapDetector.onTouchEvent(event);
return true;
}
@@ -200,4 +205,14 @@
private boolean isLandscape() {
return getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE;
}
+
+ private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener {
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (mSplitLayout != null) {
+ mSplitLayout.onDoubleTappedDivider();
+ }
+ return false;
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 291e9bd..d77def5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -55,14 +55,15 @@
private Context mContext;
private DividerSnapAlgorithm mDividerSnapAlgorithm;
private int mDividePosition;
+ private boolean mInitialized = false;
- public SplitLayout(Context context, Configuration configuration,
+ public SplitLayout(String windowName, Context context, Configuration configuration,
LayoutChangeListener layoutChangeListener,
SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks) {
mContext = context.createConfigurationContext(configuration);
mLayoutChangeListener = layoutChangeListener;
mSplitWindowManager = new SplitWindowManager(
- mContext, configuration, parentContainerCallbacks);
+ windowName, mContext, configuration, parentContainerCallbacks);
mDividerWindowWidth = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
@@ -72,8 +73,7 @@
mRootBounds.set(configuration.windowConfiguration.getBounds());
mDividerSnapAlgorithm = getSnapAlgorithm(context.getResources(), mRootBounds);
- mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position;
- updateBounds(mDividePosition);
+ resetDividerPosition();
}
/** Gets bounds of the primary split. */
@@ -112,8 +112,13 @@
mSplitWindowManager.setConfiguration(configuration);
mRootBounds.set(rootBounds);
mDividerSnapAlgorithm = getSnapAlgorithm(mContext.getResources(), mRootBounds);
- mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position;
- updateBounds(mDividePosition);
+ resetDividerPosition();
+
+ // Don't inflate divider bar if it is not initialized.
+ if (!mInitialized) {
+ return false;
+ }
+
release();
init();
return true;
@@ -141,11 +146,15 @@
/** Inflates {@link DividerView} on the root surface. */
public void init() {
+ if (mInitialized) return;
+ mInitialized = true;
mSplitWindowManager.init(this);
}
/** Releases the surface holding the current {@link DividerView}. */
public void release() {
+ if (!mInitialized) return;
+ mInitialized = false;
mSplitWindowManager.release();
}
@@ -166,6 +175,12 @@
mSplitWindowManager.setResizingSplits(false);
}
+ /** Resets divider position. */
+ public void resetDividerPosition() {
+ mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position;
+ updateBounds(mDividePosition);
+ }
+
/**
* Sets new divide position and updates bounds correspondingly. Notifies listener if the new
* target indicates dismissing split.
@@ -186,6 +201,10 @@
}
}
+ void onDoubleTappedDivider() {
+ mLayoutChangeListener.onDoubleTappedDivider();
+ }
+
/**
* Returns {@link DividerSnapAlgorithm.SnapTarget} which matches passing position and velocity.
*/
@@ -234,9 +253,15 @@
public interface LayoutChangeListener {
/** Calls when dismissing split. */
void onSnappedToDismiss(boolean snappedToEnd);
+
/** Calls when the bounds is changing due to animation or dragging divider bar. */
void onBoundsChanging(SplitLayout layout);
+
/** Calls when the target bounds changed. */
void onBoundsChanged(SplitLayout layout);
+
+ /** Calls when user double tapped on the divider bar. */
+ default void onDoubleTappedDivider() {
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 29116bd..7f9c34f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -51,22 +51,23 @@
*/
public final class SplitWindowManager extends WindowlessWindowManager {
private static final String TAG = SplitWindowManager.class.getSimpleName();
- private static final String DIVIDER_WINDOW_TITLE = "SplitDivider";
private final ParentContainerCallbacks mParentContainerCallbacks;
private Context mContext;
private SurfaceControlViewHost mViewHost;
private boolean mResizingSplits;
+ private final String mWindowName;
public interface ParentContainerCallbacks {
void attachToParentSurface(SurfaceControl.Builder b);
}
- public SplitWindowManager(Context context, Configuration config,
+ public SplitWindowManager(String windowName, Context context, Configuration config,
ParentContainerCallbacks parentContainerCallbacks) {
super(config, null /* rootSurface */, null /* hostInputToken */);
mContext = context.createConfigurationContext(config);
mParentContainerCallbacks = parentContainerCallbacks;
+ mWindowName = windowName;
}
@Override
@@ -106,7 +107,7 @@
| FLAG_SPLIT_TOUCH | FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
lp.token = new Binder();
- lp.setTitle(DIVIDER_WINDOW_TITLE);
+ lp.setTitle(mWindowName);
lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
mViewHost.setView(dividerView, lp);
dividerView.setup(splitLayout, mViewHost);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
index a891005..12b8b87 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.res.Configuration;
import android.os.SystemProperties;
+import android.util.Slog;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -28,17 +29,18 @@
import com.android.wm.shell.common.ShellExecutor;
import java.io.PrintWriter;
-import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
/**
* Manages the hide display cutout status.
*/
-public class HideDisplayCutoutController implements HideDisplayCutout {
+public class HideDisplayCutoutController {
private static final String TAG = "HideDisplayCutoutController";
private final Context mContext;
private final HideDisplayCutoutOrganizer mOrganizer;
private final ShellExecutor mMainExecutor;
+ private final HideDisplayCutoutImpl mImpl = new HideDisplayCutoutImpl();
@VisibleForTesting
boolean mEnabled;
@@ -55,7 +57,7 @@
* supported.
*/
@Nullable
- public static HideDisplayCutoutController create(
+ public static HideDisplayCutout create(
Context context, DisplayController displayController, ShellExecutor mainExecutor) {
// The SystemProperty is set for devices that support this feature and is used to control
// whether to create the HideDisplayCutout instance.
@@ -66,7 +68,7 @@
HideDisplayCutoutOrganizer organizer =
new HideDisplayCutoutOrganizer(context, displayController, mainExecutor);
- return new HideDisplayCutoutController(context, organizer, mainExecutor);
+ return new HideDisplayCutoutController(context, organizer, mainExecutor).mImpl;
}
@VisibleForTesting
@@ -88,13 +90,11 @@
}
}
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
+ private void onConfigurationChanged(Configuration newConfig) {
updateStatus();
}
- @Override
- public void dump(@NonNull PrintWriter pw) {
+ private void dump(@NonNull PrintWriter pw) {
final String prefix = " ";
pw.print(TAG);
pw.println(" states: ");
@@ -103,4 +103,22 @@
pw.println(mEnabled);
mOrganizer.dump(pw);
}
+
+ private class HideDisplayCutoutImpl implements HideDisplayCutout {
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ mMainExecutor.execute(() -> {
+ HideDisplayCutoutController.this.onConfigurationChanged(newConfig);
+ });
+ }
+
+ @Override
+ public void dump(@NonNull PrintWriter pw) {
+ try {
+ mMainExecutor.executeBlocking(() -> HideDisplayCutoutController.this.dump(pw));
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to dump HideDisplayCutoutController in 2s");
+ }
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
index c1b6c4f..e13a1db 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -36,7 +36,6 @@
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
-import android.os.Handler;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Slog;
@@ -60,7 +59,6 @@
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
-import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm;
@@ -146,8 +144,8 @@
private LegacySplitDisplayLayout mSplitLayout;
private DividerImeController mImeController;
private DividerCallbacks mCallback;
- private final AnimationHandler mAnimationHandler = new AnimationHandler();
+ private AnimationHandler mSfVsyncAnimationHandler;
private ValueAnimator mCurrentAnimator;
private boolean mEntranceAnimationRunning;
private boolean mExitAnimationRunning;
@@ -172,8 +170,6 @@
// used interact with keyguard.
private boolean mSurfaceHidden = false;
- private final Handler mHandler = new Handler();
-
private final AccessibilityDelegate mHandleDelegate = new AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
@@ -284,7 +280,10 @@
final DisplayManager displayManager =
(DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
- mAnimationHandler.setProvider(new SfVsyncFrameCallbackProvider());
+ }
+
+ public void setAnimationHandler(AnimationHandler sfVsyncAnimationHandler) {
+ mSfVsyncAnimationHandler = sfVsyncAnimationHandler;
}
@Override
@@ -669,12 +668,12 @@
} else {
final Boolean cancelled = mCancelled;
if (DEBUG) Slog.d(TAG, "Posting endFling " + cancelled + " d:" + delay + "ms");
- mHandler.postDelayed(() -> endAction.accept(cancelled), delay);
+ getHandler().postDelayed(() -> endAction.accept(cancelled), delay);
}
}
});
- anim.setAnimationHandler(mAnimationHandler);
mCurrentAnimator = anim;
+ mCurrentAnimator.setAnimationHandler(mSfVsyncAnimationHandler);
return anim;
}
@@ -1061,8 +1060,8 @@
}
}
if (getViewRootImpl() != null) {
- mHandler.removeCallbacks(mUpdateEmbeddedMatrix);
- mHandler.post(mUpdateEmbeddedMatrix);
+ getHandler().removeCallbacks(mUpdateEmbeddedMatrix);
+ getHandler().post(mUpdateEmbeddedMatrix);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
index abff69c..4fe28e6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
@@ -34,6 +34,8 @@
/**
* Translucent activity that gets started on top of a task in multi-window to inform the user that
* we forced the activity below to be resizable.
+ *
+ * Note: This activity runs on the main thread of the process hosting the Shell lib.
*/
public class ForcedResizableInfoActivity extends Activity implements OnTouchListener {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
index a785cff..bca6deb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -24,6 +24,7 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.Display.DEFAULT_DISPLAY;
+import android.animation.AnimationHandler;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
@@ -40,6 +41,8 @@
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import androidx.annotation.Nullable;
+
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -60,14 +63,14 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
/**
* Controls split screen feature.
*/
-public class LegacySplitScreenController implements LegacySplitScreen,
- DisplayController.OnDisplaysChangedListener {
+public class LegacySplitScreenController implements DisplayController.OnDisplaysChangedListener {
static final boolean DEBUG = false;
private static final String TAG = "SplitScreenCtrl";
@@ -81,11 +84,13 @@
private final DividerState mDividerState = new DividerState();
private final ForcedResizableInfoActivityController mForcedResizableController;
private final ShellExecutor mMainExecutor;
+ private final AnimationHandler mSfVsyncAnimationHandler;
private final LegacySplitScreenTaskListener mSplits;
private final SystemWindows mSystemWindows;
final TransactionPool mTransactionPool;
private final WindowManagerProxy mWindowManagerProxy;
private final TaskOrganizer mTaskOrganizer;
+ private final SplitScreenImpl mImpl = new SplitScreenImpl();
private final CopyOnWriteArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners
= new CopyOnWriteArrayList<>();
@@ -106,21 +111,37 @@
private boolean mIsKeyguardShowing;
private boolean mVisible = false;
- private boolean mMinimized = false;
- private boolean mAdjustedForIme = false;
+ private volatile boolean mMinimized = false;
+ private volatile boolean mAdjustedForIme = false;
private boolean mHomeStackResizable = false;
+ /**
+ * Creates {@link SplitScreen}, returns {@code null} if the feature is not supported.
+ */
+ @Nullable
+ public static LegacySplitScreen create(Context context,
+ DisplayController displayController, SystemWindows systemWindows,
+ DisplayImeController imeController, TransactionPool transactionPool,
+ ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
+ TaskStackListenerImpl taskStackListener, Transitions transitions,
+ ShellExecutor mainExecutor, AnimationHandler sfVsyncAnimationHandler) {
+ return new LegacySplitScreenController(context, displayController, systemWindows,
+ imeController, transactionPool, shellTaskOrganizer, syncQueue, taskStackListener,
+ transitions, mainExecutor, sfVsyncAnimationHandler).mImpl;
+ }
+
public LegacySplitScreenController(Context context,
DisplayController displayController, SystemWindows systemWindows,
DisplayImeController imeController, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
TaskStackListenerImpl taskStackListener, Transitions transitions,
- ShellExecutor mainExecutor) {
+ ShellExecutor mainExecutor, AnimationHandler sfVsyncAnimationHandler) {
mContext = context;
mDisplayController = displayController;
mSystemWindows = systemWindows;
mImeController = imeController;
mMainExecutor = mainExecutor;
+ mSfVsyncAnimationHandler = sfVsyncAnimationHandler;
mForcedResizableController = new ForcedResizableInfoActivityController(context, this,
mainExecutor);
mTransactionPool = transactionPool;
@@ -216,8 +237,7 @@
mTaskOrganizer.applyTransaction(tct);
}
- @Override
- public void onKeyguardVisibilityChanged(boolean showing) {
+ private void onKeyguardVisibilityChanged(boolean showing) {
if (!isSplitActive() || mView == null) {
return;
}
@@ -273,23 +293,19 @@
}
}
- @Override
- public DividerView getDividerView() {
- return mView;
- }
-
- @Override
- public boolean isMinimized() {
+ boolean isMinimized() {
return mMinimized;
}
- @Override
- public boolean isHomeStackResizable() {
+ boolean isHomeStackResizable() {
return mHomeStackResizable;
}
- @Override
- public boolean isDividerVisible() {
+ DividerView getDividerView() {
+ return mView;
+ }
+
+ boolean isDividerVisible() {
return mView != null && mView.getVisibility() == View.VISIBLE;
}
@@ -308,6 +324,7 @@
Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
mView = (DividerView)
LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
+ mView.setAnimationHandler(mSfVsyncAnimationHandler);
DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
mView.injectDependencies(this, mWindowManager, mDividerState, mForcedResizableController,
mSplits, mSplitLayout, mImePositionProcessor, mWindowManagerProxy);
@@ -373,8 +390,7 @@
}
}
- @Override
- public void setMinimized(final boolean minimized) {
+ private void setMinimized(final boolean minimized) {
if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
mMainExecutor.execute(() -> {
if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
@@ -437,23 +453,20 @@
mWindowManager.setTouchable(!mAdjustedForIme);
}
- @Override
- public void onUndockingTask() {
+ private void onUndockingTask() {
if (mView != null) {
mView.onUndockingTask();
}
}
- @Override
- public void onAppTransitionFinished() {
+ private void onAppTransitionFinished() {
if (mView == null) {
return;
}
mForcedResizableController.onAppTransitionFinished();
}
- @Override
- public void dump(PrintWriter pw) {
+ private void dump(PrintWriter pw) {
pw.print(" mVisible="); pw.println(mVisible);
pw.print(" mMinimized="); pw.println(mMinimized);
pw.print(" mAdjustedForIme="); pw.println(mAdjustedForIme);
@@ -469,16 +482,14 @@
return (long) (transitionDuration * transitionScale);
}
- @Override
- public void registerInSplitScreenListener(Consumer<Boolean> listener) {
+ void registerInSplitScreenListener(Consumer<Boolean> listener) {
listener.accept(isDividerVisible());
synchronized (mDockedStackExistsListeners) {
mDockedStackExistsListeners.add(new WeakReference<>(listener));
}
}
- @Override
- public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
+ void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
synchronized (mDockedStackExistsListeners) {
for (int i = mDockedStackExistsListeners.size() - 1; i >= 0; i--) {
if (mDockedStackExistsListeners.get(i) == listener) {
@@ -488,15 +499,13 @@
}
}
- @Override
- public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
+ private void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
synchronized (mBoundsChangedListeners) {
mBoundsChangedListeners.add(new WeakReference<>(listener));
}
}
- @Override
- public boolean splitPrimaryTask() {
+ private boolean splitPrimaryTask() {
try {
if (ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED
|| isSplitActive()) {
@@ -529,8 +538,7 @@
topRunningTask.taskId, true /* onTop */);
}
- @Override
- public void dismissSplitToPrimaryTask() {
+ private void dismissSplitToPrimaryTask() {
startDismissSplit(true /* toPrimaryTask */);
}
@@ -621,11 +629,136 @@
return mWindowManagerProxy;
}
- @Override
- public WindowContainerToken getSecondaryRoot() {
+ WindowContainerToken getSecondaryRoot() {
if (mSplits == null || mSplits.mSecondary == null) {
return null;
}
return mSplits.mSecondary.token;
}
+
+ private class SplitScreenImpl implements LegacySplitScreen {
+ @Override
+ public boolean isMinimized() {
+ return mMinimized;
+ }
+
+ @Override
+ public boolean isHomeStackResizable() {
+ return mHomeStackResizable;
+ }
+
+ /**
+ * TODO: Remove usage from outside the shell.
+ */
+ @Override
+ public DividerView getDividerView() {
+ return LegacySplitScreenController.this.getDividerView();
+ }
+
+ @Override
+ public boolean isDividerVisible() {
+ boolean[] result = new boolean[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = LegacySplitScreenController.this.isDividerVisible();
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to get divider visible");
+ }
+ return result[0];
+ }
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean isShowing) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.onKeyguardVisibilityChanged(isShowing);
+ });
+ }
+
+ @Override
+ public void setMinimized(boolean minimized) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.setMinimized(minimized);
+ });
+ }
+
+ @Override
+ public void onUndockingTask() {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.onUndockingTask();
+ });
+ }
+
+ @Override
+ public void onAppTransitionFinished() {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.onAppTransitionFinished();
+ });
+ }
+
+ @Override
+ public void registerInSplitScreenListener(Consumer<Boolean> listener) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.registerInSplitScreenListener(listener);
+ });
+ }
+
+ @Override
+ public void unregisterInSplitScreenListener(Consumer<Boolean> listener) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.unregisterInSplitScreenListener(listener);
+ });
+ }
+
+ @Override
+ public void registerBoundsChangeListener(BiConsumer<Rect, Rect> listener) {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.registerBoundsChangeListener(listener);
+ });
+ }
+
+ @Override
+ public WindowContainerToken getSecondaryRoot() {
+ WindowContainerToken[] result = new WindowContainerToken[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = LegacySplitScreenController.this.getSecondaryRoot();
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to get secondary root");
+ }
+ return result[0];
+ }
+
+ @Override
+ public boolean splitPrimaryTask() {
+ boolean[] result = new boolean[1];
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ result[0] = LegacySplitScreenController.this.splitPrimaryTask();
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to split primary task");
+ }
+ return result[0];
+ }
+
+ @Override
+ public void dismissSplitToPrimaryTask() {
+ mMainExecutor.execute(() -> {
+ LegacySplitScreenController.this.dismissSplitToPrimaryTask();
+ });
+ }
+
+ @Override
+ public void dump(PrintWriter pw) {
+ try {
+ mMainExecutor.executeBlocking(() -> {
+ LegacySplitScreenController.this.dump(pw);
+ });
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to dump LegacySplitScreenController in 2s");
+ }
+ }
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java
index 94b2cc0..d066cf9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/SplitScreenTransitions.java
@@ -36,6 +36,7 @@
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import com.android.wm.shell.common.TransactionPool;
@@ -76,9 +77,11 @@
}
@Override
- public WindowContainerTransaction handleRequest(@WindowManager.TransitionType int type,
- @NonNull IBinder transition, @Nullable ActivityManager.RunningTaskInfo triggerTask) {
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @Nullable TransitionRequestInfo request) {
WindowContainerTransaction out = null;
+ final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
+ final @WindowManager.TransitionType int type = request.getType();
if (mSplitScreen.isDividerVisible()) {
// try to handle everything while in split-screen
out = new WindowContainerTransaction();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
index a8cd1dd..94c6f01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
@@ -47,8 +47,6 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
/**
* Proxy to simplify calls into window manager/activity manager
@@ -77,25 +75,7 @@
@GuardedBy("mDockedRect")
private final Rect mTouchableRegion = new Rect();
- private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
-
private final SyncTransactionQueue mSyncTransactionQueue;
-
- private final Runnable mSetTouchableRegionRunnable = new Runnable() {
- @Override
- public void run() {
- try {
- synchronized (mDockedRect) {
- mTmpRect1.set(mTouchableRegion);
- }
- WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
- mTmpRect1);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to set touchable region: " + e);
- }
- }
- };
-
private final TaskOrganizer mTaskOrganizer;
WindowManagerProxy(SyncTransactionQueue syncQueue, TaskOrganizer taskOrganizer) {
@@ -108,29 +88,29 @@
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
tiles.mSplitScreenController.startDismissSplit(!dismissOrMaximize, true /* snapped */);
} else {
- mExecutor.execute(() -> applyDismissSplit(tiles, layout, dismissOrMaximize));
+ applyDismissSplit(tiles, layout, dismissOrMaximize);
}
}
public void setResizing(final boolean resizing) {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- try {
- ActivityTaskManager.getService().setSplitScreenResizing(resizing);
- } catch (RemoteException e) {
- Log.w(TAG, "Error calling setDockedStackResizing: " + e);
- }
- }
- });
+ try {
+ ActivityTaskManager.getService().setSplitScreenResizing(resizing);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error calling setDockedStackResizing: " + e);
+ }
}
/** Sets a touch region */
public void setTouchRegion(Rect region) {
- synchronized (mDockedRect) {
- mTouchableRegion.set(region);
+ try {
+ synchronized (mDockedRect) {
+ mTouchableRegion.set(region);
+ }
+ WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
+ mTouchableRegion);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to set touchable region: " + e);
}
- mExecutor.execute(mSetTouchableRegionRunnable);
}
void applyResizeSplits(int position, LegacySplitDisplayLayout splitLayout) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
index a7c34fd..d96d4d0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMediaController.java
@@ -138,7 +138,7 @@
public void onActivityPinned() {
// Once we enter PiP, try to find the active media controller for the top most activity
resolveActiveMediaController(mMediaSessionManager.getActiveSessionsForUser(null,
- UserHandle.USER_CURRENT));
+ UserHandle.CURRENT));
}
/**
@@ -245,7 +245,7 @@
public void registerSessionListenerForCurrentUser() {
mMediaSessionManager.removeOnActiveSessionsChangedListener(mSessionsChangedListener);
mMediaSessionManager.addOnActiveSessionsChangedListener(mSessionsChangedListener, null,
- UserHandle.USER_CURRENT, null);
+ UserHandle.CURRENT, null);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 519ce36..e706f76 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -152,8 +152,9 @@
public void onPipAnimationStart(PipAnimationController.PipTransitionAnimator animator) {
final int direction = animator.getTransitionDirection();
if (direction == TRANSITION_DIRECTION_TO_PIP) {
- InteractionJankMonitor.getInstance().begin(
- InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP, 2000);
+ // TODO (b//169221267): Add jank listener for transactions without buffer updates.
+ //InteractionJankMonitor.getInstance().begin(
+ // InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP, 2000);
}
sendOnPipTransitionStarted(direction);
}
@@ -166,8 +167,9 @@
animator.getAnimationType());
sendOnPipTransitionFinished(direction);
if (direction == TRANSITION_DIRECTION_TO_PIP) {
- InteractionJankMonitor.getInstance().end(
- InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP);
+ // TODO (b//169221267): Add jank listener for transactions without buffer updates.
+ //InteractionJankMonitor.getInstance().end(
+ // InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
new file mode 100644
index 0000000..552eba4
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
+import android.graphics.Rect;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+/**
+ * Main stage for split-screen mode. When split-screen is active all standard activity types launch
+ * on the main stage, except for task that are explicitly pinned to the {@link SideStage}.
+ * @see StageCoordinator
+ */
+class MainStage extends StageTaskListener {
+ private static final String TAG = MainStage.class.getSimpleName();
+
+ private boolean mIsActive = false;
+
+ private static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
+ private static final int[] CONTROLLED_WINDOWING_MODES =
+ {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
+ private static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
+ {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW};
+
+ MainStage(ShellTaskOrganizer taskOrganizer, int displayId,
+ StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue) {
+ super(taskOrganizer, displayId, callbacks, syncQueue);
+ }
+
+ boolean isActive() {
+ return mIsActive;
+ }
+
+ void activate(Rect rootBounds, WindowContainerTransaction wct) {
+ if (mIsActive) return;
+
+ final WindowContainerToken rootToken = mRootTaskInfo.token;
+ wct.setHidden(rootToken, false)
+ .setBounds(rootToken, rootBounds)
+ .setLaunchRoot(
+ rootToken,
+ CONTROLLED_WINDOWING_MODES,
+ CONTROLLED_ACTIVITY_TYPES)
+ .reparentTasks(
+ null /* currentParent */,
+ rootToken,
+ CONTROLLED_WINDOWING_MODES,
+ CONTROLLED_ACTIVITY_TYPES,
+ true /* onTop */)
+ // Moving the root task to top after the child tasks were repareted , or the root
+ // task cannot be visible and focused.
+ .reorder(rootToken, true /* onTop */);
+
+ mIsActive = true;
+ }
+
+ void deactivate(WindowContainerTransaction wct) {
+ if (!mIsActive) return;
+ mIsActive = false;
+
+ if (mRootTaskInfo == null) return;
+ final WindowContainerToken rootToken = mRootTaskInfo.token;
+ wct.setHidden(rootToken, true)
+ .setLaunchRoot(
+ rootToken,
+ null,
+ null)
+ .reparentTasks(
+ rootToken,
+ null /* newParent */,
+ CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
+ CONTROLLED_ACTIVITY_TYPES,
+ true /* onTop */)
+ .reorder(rootToken, false /* onTop */);
+ }
+
+ void updateConfiguration(int windowingMode, Rect bounds, WindowContainerTransaction wct) {
+ wct.setBounds(mRootTaskInfo.token, bounds)
+ .setWindowingMode(mRootTaskInfo.token, windowingMode);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
new file mode 100644
index 0000000..5645c19
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import android.app.ActivityManager;
+import android.graphics.Rect;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+/**
+ * Side stage for split-screen mode. Only tasks that are explicitly pinned to this stage show up
+ * here. All other task are launch in the {@link MainStage}.
+ * @see StageCoordinator
+ */
+class SideStage extends StageTaskListener {
+ private static final String TAG = SideStage.class.getSimpleName();
+
+ SideStage(ShellTaskOrganizer taskOrganizer, int displayId,
+ StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue) {
+ super(taskOrganizer, displayId, callbacks, syncQueue);
+ }
+
+ void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds,
+ WindowContainerTransaction wct) {
+ final WindowContainerToken rootToken = mRootTaskInfo.token;
+ wct.setHidden(rootToken, false)
+ .setBounds(rootToken, rootBounds)
+ .reparent(task.token, rootToken, true /* onTop*/)
+ // Moving the root task to top after the child tasks were repareted , or the root
+ // task cannot be visible and focused.
+ .reorder(rootToken, true);
+ }
+
+ boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) {
+ final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId);
+ if (task == null) return false;
+
+ wct.setHidden(mRootTaskInfo.token, true)
+ .reorder(mRootTaskInfo.token, false)
+ .reparent(task.token, newParent, false /* onTop */);
+ return true;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
new file mode 100644
index 0000000..08c2856
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import android.annotation.IntDef;
+import android.app.ActivityManager;
+
+import androidx.annotation.NonNull;
+
+import com.android.wm.shell.common.annotations.ExternalThread;
+
+import java.io.PrintWriter;
+
+/**
+ * Interface to engage split-screen feature.
+ */
+@ExternalThread
+public interface SplitScreen {
+ /**
+ * Specifies that the side-stage is positioned at the top half of the screen if
+ * in portrait mode or at the left half of the screen if in landscape mode.
+ */
+ int SIDE_STAGE_POSITION_TOP_OR_LEFT = 0;
+
+ /**
+ * Specifies that the side-stage is positioned at the bottom half of the screen if
+ * in portrait mode or at the right half of the screen if in landscape mode.
+ */
+ int SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT = 1;
+
+ @IntDef(prefix = { "SIDE_STAGE_POSITION_" }, value = {
+ SIDE_STAGE_POSITION_TOP_OR_LEFT,
+ SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT
+ })
+ @interface SideStagePosition {}
+
+ /** @return {@code true} if split-screen is currently visible. */
+ boolean isSplitScreenVisible();
+ /** Moves a task in the side-stage of split-screen. */
+ boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition);
+ /** Moves a task in the side-stage of split-screen. */
+ boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
+ @SideStagePosition int sideStagePosition);
+ /** Removes a task from the side-stage of split-screen. */
+ boolean removeFromSideStage(int taskId);
+ /** Sets the position of the side-stage. */
+ void setSideStagePosition(@SideStagePosition int sideStagePosition);
+ /** Hides the side-stage if it is currently visible. */
+ void setSideStageVisibility(boolean visible);
+ /** Dumps current status of split-screen. */
+ void dump(@NonNull PrintWriter pw, String prefix);
+ /** Called when the shell organizer has been registered. */
+ void onOrganizerRegistered();
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
new file mode 100644
index 0000000..55cfea5
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.app.ActivityManager;
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import java.io.PrintWriter;
+
+/**
+ * Class manages split-screen multitasking mode and implements the main interface
+ * {@link SplitScreen}.
+ * @see StageCoordinator
+ */
+public class SplitScreenController implements SplitScreen {
+ private static final String TAG = SplitScreenController.class.getSimpleName();
+
+ private final ShellTaskOrganizer mTaskOrganizer;
+ private final SyncTransactionQueue mSyncQueue;
+ private final Context mContext;
+ private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
+ private StageCoordinator mStageCoordinator;
+
+ public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
+ SyncTransactionQueue syncQueue, Context context,
+ RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
+ mTaskOrganizer = shellTaskOrganizer;
+ mSyncQueue = syncQueue;
+ mContext = context;
+ mRootTDAOrganizer = rootTDAOrganizer;
+ }
+
+ @Override
+ public void onOrganizerRegistered() {
+ if (mStageCoordinator == null) {
+ // TODO: Multi-display
+ mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
+ mRootTDAOrganizer, mTaskOrganizer);
+ }
+ }
+
+ @Override
+ public boolean isSplitScreenVisible() {
+ return mStageCoordinator.isSplitScreenVisible();
+ }
+
+ @Override
+ public boolean moveToSideStage(int taskId, @SideStagePosition int sideStagePosition) {
+ final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
+ return task != null && moveToSideStage(task, sideStagePosition);
+ }
+
+ @Override
+ public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
+ @SideStagePosition int sideStagePosition) {
+ return mStageCoordinator.moveToSideStage(task, sideStagePosition);
+ }
+
+ @Override
+ public boolean removeFromSideStage(int taskId) {
+ return mStageCoordinator.removeFromSideStage(taskId);
+ }
+
+ @Override
+ public void setSideStagePosition(@SideStagePosition int sideStagePosition) {
+ mStageCoordinator.setSideStagePosition(sideStagePosition);
+ }
+
+ @Override
+ public void setSideStageVisibility(boolean visible) {
+ mStageCoordinator.setSideStageVisibility(visible);
+ }
+
+ @Override
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ pw.println(prefix + TAG);
+ if (mStageCoordinator != null) {
+ mStageCoordinator.dump(pw, prefix);
+ }
+ }
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
new file mode 100644
index 0000000..bdac37a
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+
+import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_TOP_OR_LEFT;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.SurfaceControl;
+import android.window.DisplayAreaInfo;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.split.SplitLayout;
+
+import java.io.PrintWriter;
+
+/**
+ * Coordinates the staging (visibility, sizing, ...) of the split-screen {@link MainStage} and
+ * {@link SideStage} stages.
+ * Some high-level rules:
+ * - The {@link StageCoordinator} is only considered active if the {@link SideStage} contains at
+ * least one child task.
+ * - The {@link MainStage} should only have children if the coordinator is active.
+ * - The {@link SplitLayout} divider is only visible if both the {@link MainStage}
+ * and {@link SideStage} are visible.
+ * - The {@link MainStage} configuration is fullscreen when the {@link SideStage} isn't visible.
+ * This rules are mostly implemented in {@link #onStageVisibilityChanged(StageListenerImpl)} and
+ * {@link #onStageHasChildrenChanged(StageListenerImpl).}
+ */
+class StageCoordinator implements SplitLayout.LayoutChangeListener,
+ RootTaskDisplayAreaOrganizer.RootTaskDisplayAreaListener {
+
+ private static final String TAG = StageCoordinator.class.getSimpleName();
+
+ private final MainStage mMainStage;
+ private final StageListenerImpl mMainStageListener = new StageListenerImpl();
+ private final SideStage mSideStage;
+ private final StageListenerImpl mSideStageListener = new StageListenerImpl();
+ private @SplitScreen.SideStagePosition int mSideStagePosition =
+ SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
+
+ private final int mDisplayId;
+ private SplitLayout mSplitLayout;
+ private boolean mDividerVisible;
+ private final SyncTransactionQueue mSyncQueue;
+ private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
+ private final ShellTaskOrganizer mTaskOrganizer;
+ private DisplayAreaInfo mDisplayAreaInfo;
+ private final Context mContext;
+
+ StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
+ RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer) {
+ mContext = context;
+ mDisplayId = displayId;
+ mSyncQueue = syncQueue;
+ mRootTDAOrganizer = rootTDAOrganizer;
+ mTaskOrganizer = taskOrganizer;
+ mMainStage = new MainStage(mTaskOrganizer, mDisplayId, mMainStageListener, mSyncQueue);
+ mSideStage = new SideStage(mTaskOrganizer, mDisplayId, mSideStageListener, mSyncQueue);
+ mRootTDAOrganizer.registerListener(displayId, this);
+ }
+
+ @VisibleForTesting
+ StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
+ RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
+ MainStage mainStage, SideStage sideStage) {
+ mContext = context;
+ mDisplayId = displayId;
+ mSyncQueue = syncQueue;
+ mRootTDAOrganizer = rootTDAOrganizer;
+ mTaskOrganizer = taskOrganizer;
+ mMainStage = mainStage;
+ mSideStage = sideStage;
+ mRootTDAOrganizer.registerListener(displayId, this);
+ }
+
+ boolean isSplitScreenVisible() {
+ return mSideStageListener.mVisible && mMainStageListener.mVisible;
+ }
+
+ boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
+ @SplitScreen.SideStagePosition int sideStagePosition) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mSideStagePosition = sideStagePosition;
+ mMainStage.activate(getMainStageBounds(), wct);
+ mSideStage.addTask(task, getSideStageBounds(), wct);
+ mTaskOrganizer.applyTransaction(wct);
+ return true;
+ }
+
+ boolean removeFromSideStage(int taskId) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+
+ /**
+ * {@link MainStage} will be deactivated in {@link #onStageHasChildrenChanged} if the
+ * {@link SideStage} no longer has children.
+ */
+ final boolean result = mSideStage.removeTask(taskId,
+ mMainStage.isActive() ? mMainStage.mRootTaskInfo.token : null,
+ wct);
+ mTaskOrganizer.applyTransaction(wct);
+ return result;
+ }
+
+ void setSideStagePosition(@SplitScreen.SideStagePosition int sideStagePosition) {
+ mSideStagePosition = sideStagePosition;
+ if (mSideStageListener.mVisible) {
+ onStageVisibilityChanged(mSideStageListener);
+ }
+ }
+
+ void setSideStageVisibility(boolean visible) {
+ if (!mSideStageListener.mVisible == visible) return;
+
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mSideStage.setVisibility(visible, wct);
+ mTaskOrganizer.applyTransaction(wct);
+ }
+
+ private void onStageRootTaskVanished(StageListenerImpl stageListener) {
+ if (stageListener == mMainStageListener || stageListener == mSideStageListener) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ // Deactivate the main stage if it no longer has a root task.
+ mMainStage.deactivate(wct);
+ mTaskOrganizer.applyTransaction(wct);
+ }
+ }
+
+ private void onStageVisibilityChanged(StageListenerImpl stageListener) {
+ final boolean sideStageVisible = mSideStageListener.mVisible;
+ final boolean mainStageVisible = mMainStageListener.mVisible;
+ // Divider is only visible if both the main stage and side stages are visible
+ final boolean dividerVisible = sideStageVisible && mainStageVisible;
+
+ if (mDividerVisible != dividerVisible) {
+ mDividerVisible = dividerVisible;
+ if (mDividerVisible) {
+ mSplitLayout.init();
+ } else {
+ mSplitLayout.release();
+ }
+ }
+
+ if (mainStageVisible) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ if (sideStageVisible) {
+ // The main stage configuration should to follow split layout when side stage is
+ // visible.
+ mMainStage.updateConfiguration(
+ WINDOWING_MODE_MULTI_WINDOW, getMainStageBounds(), wct);
+ } else {
+ // We want the main stage configuration to be fullscreen when the side stage isn't
+ // visible.
+ mMainStage.updateConfiguration(WINDOWING_MODE_FULLSCREEN, null, wct);
+ }
+ // TODO: Change to `mSyncQueue.queue(wct)` once BLAST is stable.
+ mTaskOrganizer.applyTransaction(wct);
+ }
+
+ mSyncQueue.runInSync(t -> {
+ final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
+ final SurfaceControl sideStageLeash = mSideStage.mRootLeash;
+ final SurfaceControl mainStageLeash = mMainStage.mRootLeash;
+
+ if (dividerLeash != null) {
+ if (mDividerVisible) {
+ t.show(dividerLeash)
+ .setLayer(dividerLeash, Integer.MAX_VALUE)
+ .setPosition(dividerLeash,
+ mSplitLayout.getDividerBounds().left,
+ mSplitLayout.getDividerBounds().top);
+ } else {
+ t.hide(dividerLeash);
+ }
+ }
+
+ if (sideStageVisible) {
+ final Rect sideStageBounds = getSideStageBounds();
+ t.show(sideStageLeash)
+ .setPosition(sideStageLeash,
+ sideStageBounds.left, sideStageBounds.top)
+ .setWindowCrop(sideStageLeash,
+ sideStageBounds.width(), sideStageBounds.height());
+ } else {
+ t.hide(sideStageLeash);
+ }
+
+ if (mainStageVisible) {
+ final Rect mainStageBounds = getMainStageBounds();
+ t.show(mainStageLeash);
+ if (sideStageVisible) {
+ t.setPosition(mainStageLeash, mainStageBounds.left, mainStageBounds.top)
+ .setWindowCrop(mainStageLeash,
+ mainStageBounds.width(), mainStageBounds.height());
+ } else {
+ // Clear window crop and position if side stage isn't visible.
+ t.setPosition(mainStageLeash, 0, 0)
+ .setWindowCrop(mainStageLeash, null);
+ }
+ } else {
+ t.hide(mainStageLeash);
+ }
+ });
+ }
+
+ private void onStageHasChildrenChanged(StageListenerImpl stageListener) {
+ if (stageListener == mSideStageListener) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ if (mSideStageListener.mHasChildren) {
+ // Make sure the main stage is active.
+ mMainStage.activate(getMainStageBounds(), wct);
+ } else {
+ // The side stage no long has children so we can deactivate the main stage.
+ mMainStage.deactivate(wct);
+ }
+ mTaskOrganizer.applyTransaction(wct);
+ }
+ }
+
+ @Override
+ public void onSnappedToDismiss(boolean snappedToEnd) {
+ // TODO: What to do...what to do...
+ mSplitLayout.resetDividerPosition();
+ onBoundsChanged(mSplitLayout);
+ }
+
+ @Override
+ public void onBoundsChanging(SplitLayout layout) {
+ final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
+ if (dividerLeash == null) return;
+ final Rect mainStageBounds = getMainStageBounds();
+ final Rect sideStageBounds = getSideStageBounds();
+
+ mSyncQueue.runInSync(t -> t
+ .setPosition(dividerLeash,
+ mSplitLayout.getDividerBounds().left, mSplitLayout.getDividerBounds().top)
+ .setPosition(mMainStage.mRootLeash, mainStageBounds.left, mainStageBounds.top)
+ .setPosition(mSideStage.mRootLeash, sideStageBounds.left, sideStageBounds.top)
+ // Sets crop to prevent visible region of tasks overlap with each other when
+ // re-positioning surfaces while resizing.
+ .setWindowCrop(mMainStage.mRootLeash,
+ mainStageBounds.width(), mainStageBounds.height())
+ .setWindowCrop(mSideStage.mRootLeash,
+ sideStageBounds.width(), sideStageBounds.height()));
+
+ }
+
+ @Override
+ public void onDoubleTappedDivider() {
+ setSideStagePosition(mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT
+ ? SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT : SIDE_STAGE_POSITION_TOP_OR_LEFT);
+ }
+
+ @Override
+ public void onBoundsChanged(SplitLayout layout) {
+ final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
+ if (dividerLeash == null) return;
+ final Rect mainStageBounds = getMainStageBounds();
+ final Rect sideStageBounds = getSideStageBounds();
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ mMainStage.setBounds(mainStageBounds, wct);
+ mSideStage.setBounds(sideStageBounds, wct);
+ mTaskOrganizer.applyTransaction(wct);
+
+ mSyncQueue.runInSync(t -> t
+ // Resets layer of divider bar to make sure it is always on top.
+ .setLayer(dividerLeash, Integer.MAX_VALUE)
+ .setPosition(dividerLeash,
+ mSplitLayout.getDividerBounds().left, mSplitLayout.getDividerBounds().top)
+ .setPosition(mMainStage.mRootLeash,
+ mainStageBounds.left, mainStageBounds.top)
+ .setPosition(mSideStage.mRootLeash,
+ sideStageBounds.left, sideStageBounds.top)
+ // Resets crop to apply new surface bounds directly.
+ .setWindowCrop(mMainStage.mRootLeash, null)
+ .setWindowCrop(mSideStage.mRootLeash, null));
+ }
+
+ @Override
+ public void onDisplayAreaAppeared(DisplayAreaInfo displayAreaInfo) {
+ mDisplayAreaInfo = displayAreaInfo;
+ if (mSplitLayout == null) {
+ mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
+ mDisplayAreaInfo.configuration, this,
+ b -> mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b));
+ }
+ }
+
+ @Override
+ public void onDisplayAreaVanished(DisplayAreaInfo displayAreaInfo) {
+ throw new IllegalStateException("Well that was unexpected...");
+ }
+
+ @Override
+ public void onDisplayAreaInfoChanged(DisplayAreaInfo displayAreaInfo) {
+ mDisplayAreaInfo = displayAreaInfo;
+ if (mSplitLayout != null
+ && mSplitLayout.updateConfiguration(mDisplayAreaInfo.configuration)) {
+ onBoundsChanged(mSplitLayout);
+ }
+ }
+
+ private Rect getSideStageBounds() {
+ return mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT
+ ? mSplitLayout.getBounds1() : mSplitLayout.getBounds2();
+ }
+
+ private Rect getMainStageBounds() {
+ return mSideStagePosition == SIDE_STAGE_POSITION_TOP_OR_LEFT
+ ? mSplitLayout.getBounds2() : mSplitLayout.getBounds1();
+ }
+
+ @Override
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ final String childPrefix = innerPrefix + " ";
+ pw.println(prefix + TAG + " mDisplayId=" + mDisplayId);
+ pw.println(innerPrefix + "mDividerVisible=" + mDividerVisible);
+ pw.println(innerPrefix + "MainStage");
+ pw.println(childPrefix + "isActive=" + mMainStage.isActive());
+ mMainStageListener.dump(pw, childPrefix);
+ pw.println(innerPrefix + "SideStage");
+ mSideStageListener.dump(pw, childPrefix);
+ pw.println(innerPrefix + "mSplitLayout=" + mSplitLayout);
+ }
+
+ class StageListenerImpl implements StageTaskListener.StageListenerCallbacks {
+ boolean mHasRootTask = false;
+ boolean mVisible = false;
+ boolean mHasChildren = false;
+
+ @Override
+ public void onRootTaskAppeared() {
+ mHasRootTask = true;
+ }
+
+ @Override
+ public void onStatusChanged(boolean visible, boolean hasChildren) {
+ if (!mHasRootTask) return;
+
+ if (mHasChildren != hasChildren) {
+ mHasChildren = hasChildren;
+ StageCoordinator.this.onStageHasChildrenChanged(this);
+ }
+ if (mVisible != visible) {
+ mVisible = visible;
+ StageCoordinator.this.onStageVisibilityChanged(this);
+ }
+ }
+
+ @Override
+ public void onRootTaskVanished() {
+ reset();
+ StageCoordinator.this.onStageRootTaskVanished(this);
+ }
+
+ private void reset() {
+ mHasRootTask = false;
+ mVisible = false;
+ mHasChildren = false;
+ }
+
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ pw.println(prefix + "mHasRootTask=" + mHasRootTask);
+ pw.println(prefix + "mVisible=" + mVisible);
+ pw.println(prefix + "mHasChildren=" + mHasChildren);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
new file mode 100644
index 0000000..30f2701
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+
+import android.annotation.CallSuper;
+import android.app.ActivityManager;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.SparseArray;
+import android.view.SurfaceControl;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.transition.Transitions;
+
+import java.io.PrintWriter;
+
+/**
+ * Base class that handle common task org. related for split-screen stages.
+ * Note that this class and its sub-class do not directly perform hierarchy operations.
+ * They only serve to hold a collection of tasks and provide APIs like
+ * {@link #setBounds(Rect, WindowContainerTransaction)} for the centralized {@link StageCoordinator}
+ * to perform operations in-sync with other containers.
+ * @see StageCoordinator
+ */
+class StageTaskListener implements ShellTaskOrganizer.TaskListener {
+ private static final String TAG = StageTaskListener.class.getSimpleName();
+
+ /** Callback interface for listening to changes in a split-screen stage. */
+ public interface StageListenerCallbacks {
+ void onRootTaskAppeared();
+ void onStatusChanged(boolean visible, boolean hasChildren);
+ void onRootTaskVanished();
+ }
+ private final StageListenerCallbacks mCallbacks;
+ private final SyncTransactionQueue mSyncQueue;
+
+ protected ActivityManager.RunningTaskInfo mRootTaskInfo;
+ protected SurfaceControl mRootLeash;
+ protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
+ private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
+
+ StageTaskListener(ShellTaskOrganizer taskOrganizer, int displayId,
+ StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue) {
+ mCallbacks = callbacks;
+ mSyncQueue = syncQueue;
+ taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
+ }
+
+ @Override
+ @CallSuper
+ public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
+ if (!taskInfo.hasParentTask()) {
+ mCallbacks.onRootTaskAppeared();
+ mRootLeash = leash;
+ mRootTaskInfo = taskInfo;
+ } else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
+ mChildrenLeashes.put(taskInfo.taskId, leash);
+ mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
+ updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
+ } else {
+ throw new IllegalArgumentException("Unknown task: " + taskInfo);
+ }
+ sendStatusChanged();
+ }
+
+ @Override
+ @CallSuper
+ public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ if (mRootTaskInfo.taskId == taskInfo.taskId) {
+ mRootTaskInfo = taskInfo;
+ } else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
+ mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
+ updateChildTaskSurface(
+ taskInfo, mChildrenLeashes.get(taskInfo.taskId), false /* firstAppeared */);
+ } else {
+ throw new IllegalArgumentException("Unknown task: " + taskInfo);
+ }
+ sendStatusChanged();
+ }
+
+ @Override
+ @CallSuper
+ public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
+ final int taskId = taskInfo.taskId;
+ if (mRootTaskInfo.taskId == taskId) {
+ mCallbacks.onRootTaskVanished();
+ mRootTaskInfo = null;
+ } else if (mChildrenTaskInfo.contains(taskId)) {
+ mChildrenTaskInfo.remove(taskId);
+ mChildrenLeashes.remove(taskId);
+ sendStatusChanged();
+ } else {
+ throw new IllegalArgumentException("Unknown task: " + taskInfo);
+ }
+ }
+
+ void setBounds(Rect bounds, WindowContainerTransaction wct) {
+ wct.setBounds(mRootTaskInfo.token, bounds);
+ }
+
+ void setVisibility(boolean visible, WindowContainerTransaction wct) {
+ wct.reorder(mRootTaskInfo.token, visible /* onTop */);
+ }
+
+ private void updateChildTaskSurface(ActivityManager.RunningTaskInfo taskInfo,
+ SurfaceControl leash, boolean firstAppeared) {
+ final Point taskPositionInParent = taskInfo.positionInParent;
+ mSyncQueue.runInSync(t -> {
+ t.setWindowCrop(leash, null);
+ t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
+ if (firstAppeared && !Transitions.ENABLE_SHELL_TRANSITIONS) {
+ t.setAlpha(leash, 1f);
+ t.setMatrix(leash, 1, 0, 0, 1);
+ t.show(leash);
+ }
+ });
+ }
+
+ private void sendStatusChanged() {
+ mCallbacks.onStatusChanged(mRootTaskInfo.isVisible, mChildrenTaskInfo.size() > 0);
+ }
+
+ @Override
+ @CallSuper
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
new file mode 100644
index 0000000..f1e06f7
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.util.ArrayMap;
+import android.view.SurfaceControl;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TransactionPool;
+
+import java.util.ArrayList;
+
+/** The default handler that handles anything not already handled. */
+public class DefaultTransitionHandler implements Transitions.TransitionHandler {
+ private final TransactionPool mTransactionPool;
+ private final ShellExecutor mMainExecutor;
+ private final ShellExecutor mAnimExecutor;
+
+ /** Keeps track of the currently-running animations associated with each transition. */
+ private final ArrayMap<IBinder, ArrayList<Animator>> mAnimations = new ArrayMap<>();
+
+ DefaultTransitionHandler(@NonNull TransactionPool transactionPool,
+ @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
+ mTransactionPool = transactionPool;
+ mMainExecutor = mainExecutor;
+ mAnimExecutor = animExecutor;
+ }
+
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {
+ if (mAnimations.containsKey(transition)) {
+ throw new IllegalStateException("Got a duplicate startAnimation call for "
+ + transition);
+ }
+ final ArrayList<Animator> animations = new ArrayList<>();
+ mAnimations.put(transition, animations);
+ final boolean isOpening = Transitions.isOpeningType(info.getType());
+
+ final Runnable onAnimFinish = () -> {
+ if (!animations.isEmpty()) return;
+ mAnimations.remove(transition);
+ finishCallback.run();
+ };
+ for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+
+ // Don't animate anything with an animating parent
+ if (change.getParent() != null) continue;
+
+ final int mode = change.getMode();
+ if (isOpening && (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
+ if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
+ // This received a transferred starting window, so don't animate
+ continue;
+ }
+ // fade in
+ startExampleAnimation(
+ animations, change.getLeash(), true /* show */, onAnimFinish);
+ } else if (!isOpening && (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK)) {
+ // fade out
+ startExampleAnimation(
+ animations, change.getLeash(), false /* show */, onAnimFinish);
+ }
+ }
+ t.apply();
+ // run finish now in-case there are no animations
+ onAnimFinish.run();
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ return null;
+ }
+
+ // TODO(shell-transitions): real animations
+ private void startExampleAnimation(@NonNull ArrayList<Animator> animations,
+ @NonNull SurfaceControl leash, boolean show, @NonNull Runnable finishCallback) {
+ final float end = show ? 1.f : 0.f;
+ final float start = 1.f - end;
+ final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
+ final ValueAnimator va = ValueAnimator.ofFloat(start, end);
+ va.setDuration(500);
+ va.addUpdateListener(animation -> {
+ float fraction = animation.getAnimatedFraction();
+ transaction.setAlpha(leash, start * (1.f - fraction) + end * fraction);
+ transaction.apply();
+ });
+ final Runnable finisher = () -> {
+ transaction.setAlpha(leash, end);
+ transaction.apply();
+ mTransactionPool.release(transaction);
+ mMainExecutor.execute(() -> {
+ animations.remove(va);
+ finishCallback.run();
+ });
+ };
+ va.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) { }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finisher.run();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ finisher.run();
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) { }
+ });
+ animations.add(va);
+ mAnimExecutor.execute(va::start);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
new file mode 100644
index 0000000..cf141c6a
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Pair;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.SurfaceControl;
+import android.window.IRemoteTransition;
+import android.window.TransitionFilter;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.common.ShellExecutor;
+
+import java.util.ArrayList;
+
+/**
+ * Handler that deals with RemoteTransitions. It will only request to handle a transition
+ * if the request includes a specific remote.
+ */
+public class RemoteTransitionHandler implements Transitions.TransitionHandler {
+ private final ShellExecutor mMainExecutor;
+
+ /** Includes remotes explicitly requested by, eg, ActivityOptions */
+ private final ArrayMap<IBinder, IRemoteTransition> mPendingRemotes = new ArrayMap<>();
+
+ /** Ordered by specificity. Last filters will be checked first */
+ private final ArrayList<Pair<TransitionFilter, IRemoteTransition>> mFilters =
+ new ArrayList<>();
+
+ RemoteTransitionHandler(@NonNull ShellExecutor mainExecutor) {
+ mMainExecutor = mainExecutor;
+ }
+
+ void addFiltered(TransitionFilter filter, IRemoteTransition remote) {
+ mFilters.add(new Pair<TransitionFilter, IRemoteTransition>(filter, remote));
+ }
+
+ void removeFiltered(IRemoteTransition remote) {
+ for (int i = mFilters.size() - 1; i >= 0; --i) {
+ if (mFilters.get(i).second == remote) {
+ mFilters.remove(i);
+ }
+ }
+ }
+
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {
+ IRemoteTransition pendingRemote = mPendingRemotes.remove(transition);
+ if (pendingRemote == null) {
+ // If no explicit remote, search filters until one matches
+ for (int i = mFilters.size() - 1; i >= 0; --i) {
+ if (mFilters.get(i).first.matches(info)) {
+ pendingRemote = mFilters.get(i).second;
+ break;
+ }
+ }
+ }
+
+ if (pendingRemote == null) return false;
+
+ final IRemoteTransition remote = pendingRemote;
+ final IBinder.DeathRecipient remoteDied = () -> {
+ Log.e(Transitions.TAG, "Remote transition died, finishing");
+ mMainExecutor.execute(finishCallback);
+ };
+ IRemoteAnimationFinishedCallback cb = new IRemoteAnimationFinishedCallback.Stub() {
+ @Override
+ public void onAnimationFinished() throws RemoteException {
+ if (remote.asBinder() != null) {
+ remote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
+ }
+ mMainExecutor.execute(finishCallback);
+ }
+ };
+ try {
+ if (remote.asBinder() != null) {
+ remote.asBinder().linkToDeath(remoteDied, 0 /* flags */);
+ }
+ remote.startAnimation(info, t, cb);
+ } catch (RemoteException e) {
+ Log.e(Transitions.TAG, "Error running remote transition.", e);
+ mMainExecutor.execute(finishCallback);
+ }
+ return true;
+ }
+
+ @Override
+ @Nullable
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @Nullable TransitionRequestInfo request) {
+ IRemoteTransition remote = request.getRemoteTransition();
+ if (remote == null) return null;
+ mPendingRemotes.put(transition, remote);
+ return new WindowContainerTransaction();
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 7ce71b0..c085168 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -23,51 +23,54 @@
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
-import android.animation.Animator;
-import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.util.ArrayMap;
+import android.util.Log;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import android.window.IRemoteTransition;
import android.window.ITransitionPlayer;
+import android.window.TransitionFilter;
import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
import androidx.annotation.BinderThread;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import java.util.ArrayList;
+import java.util.Arrays;
/** Plays transition animations */
public class Transitions {
- private static final String TAG = "ShellTransitions";
+ static final String TAG = "ShellTransitions";
/** Set to {@code true} to enable shell transitions. */
public static final boolean ENABLE_SHELL_TRANSITIONS =
SystemProperties.getBoolean("persist.debug.shell_transit", false);
private final WindowOrganizer mOrganizer;
- private final TransactionPool mTransactionPool;
private final ShellExecutor mMainExecutor;
private final ShellExecutor mAnimExecutor;
private final TransitionPlayerImpl mPlayerImpl;
+ private final RemoteTransitionHandler mRemoteTransitionHandler;
/** List of possible handlers. Ordered by specificity (eg. tapped back to front). */
private final ArrayList<TransitionHandler> mHandlers = new ArrayList<>();
private static final class ActiveTransition {
- ArrayList<Animator> mAnimations = null;
TransitionHandler mFirstHandler = null;
}
@@ -77,14 +80,33 @@
public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool,
@NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) {
mOrganizer = organizer;
- mTransactionPool = pool;
mMainExecutor = mainExecutor;
mAnimExecutor = animExecutor;
mPlayerImpl = new TransitionPlayerImpl();
+ // The very last handler (0 in the list) should be the default one.
+ mHandlers.add(new DefaultTransitionHandler(pool, mainExecutor, animExecutor));
+ // Next lowest priority is remote transitions.
+ mRemoteTransitionHandler = new RemoteTransitionHandler(mainExecutor);
+ mHandlers.add(mRemoteTransitionHandler);
+ }
+
+ private Transitions() {
+ mOrganizer = null;
+ mMainExecutor = null;
+ mAnimExecutor = null;
+ mPlayerImpl = null;
+ mRemoteTransitionHandler = null;
+ }
+
+ /** Create an empty/non-registering transitions object for system-ui tests. */
+ @VisibleForTesting
+ public static Transitions createEmptyForTesting() {
+ return new Transitions();
}
/** Register this transition handler with Core */
public void register(ShellTaskOrganizer taskOrganizer) {
+ if (mPlayerImpl == null) return;
taskOrganizer.registerTransitionPlayer(mPlayerImpl);
}
@@ -104,47 +126,23 @@
return mAnimExecutor;
}
- // TODO(shell-transitions): real animations
- private void startExampleAnimation(@NonNull IBinder transition, @NonNull SurfaceControl leash,
- boolean show) {
- final float end = show ? 1.f : 0.f;
- final float start = 1.f - end;
- final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
- final ValueAnimator va = ValueAnimator.ofFloat(start, end);
- va.setDuration(500);
- va.addUpdateListener(animation -> {
- float fraction = animation.getAnimatedFraction();
- transaction.setAlpha(leash, start * (1.f - fraction) + end * fraction);
- transaction.apply();
- });
- final Runnable finisher = () -> {
- transaction.setAlpha(leash, end);
- transaction.apply();
- mTransactionPool.release(transaction);
- mMainExecutor.execute(() -> {
- mActiveTransitions.get(transition).mAnimations.remove(va);
- onFinish(transition);
- });
- };
- va.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) { }
+ /** Only use this in tests. This is used to avoid running animations during tests. */
+ @VisibleForTesting
+ void replaceDefaultHandlerForTest(TransitionHandler handler) {
+ mHandlers.set(0, handler);
+ }
- @Override
- public void onAnimationEnd(Animator animation) {
- finisher.run();
- }
+ /** Register a remote transition to be used when `filter` matches an incoming transition */
+ @ExternalThread
+ public void registerRemote(@NonNull TransitionFilter filter,
+ @NonNull IRemoteTransition remoteTransition) {
+ mMainExecutor.execute(() -> mRemoteTransitionHandler.addFiltered(filter, remoteTransition));
+ }
- @Override
- public void onAnimationCancel(Animator animation) {
- finisher.run();
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) { }
- });
- mActiveTransitions.get(transition).mAnimations.add(va);
- mAnimExecutor.execute(va::start);
+ /** Unregisters a remote transition and all associated filters */
+ @ExternalThread
+ public void unregisterRemote(@NonNull IRemoteTransition remoteTransition) {
+ mMainExecutor.execute(() -> mRemoteTransitionHandler.removeFiltered(remoteTransition));
}
/** @return true if the transition was triggered by opening something vs closing something */
@@ -164,6 +162,8 @@
if (info.getRootLeash().isValid()) {
t.show(info.getRootLeash());
}
+ // Put animating stuff above this line and put static stuff below it.
+ int zSplitLine = info.getChanges().size();
// changes should be ordered top-to-bottom in z
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
@@ -190,7 +190,7 @@
t.setMatrix(leash, 1, 0, 0, 1);
if (isOpening) {
// put on top with 0 alpha
- t.setLayer(leash, info.getChanges().size() - i);
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
// This received a transferred starting window, so make it immediately
// visible.
@@ -200,35 +200,33 @@
}
} else {
// put on bottom and leave it visible
- t.setLayer(leash, -i);
+ t.setLayer(leash, zSplitLine - i);
t.setAlpha(leash, 1.f);
}
} else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
if (isOpening) {
// put on bottom and leave visible
- t.setLayer(leash, -i);
+ t.setLayer(leash, zSplitLine - i);
} else {
// put on top
- t.setLayer(leash, info.getChanges().size() - i);
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
}
} else { // CHANGE
- t.setLayer(leash, info.getChanges().size() - i);
+ t.setLayer(leash, zSplitLine + info.getChanges().size() - i);
}
}
}
- private void onTransitionReady(@NonNull IBinder transitionToken, @NonNull TransitionInfo info,
+ @VisibleForTesting
+ void onTransitionReady(@NonNull IBinder transitionToken, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "onTransitionReady %s: %s",
transitionToken, info);
final ActiveTransition active = mActiveTransitions.get(transitionToken);
if (active == null) {
throw new IllegalStateException("Got transitionReady for non-active transition "
- + transitionToken + ". expecting one of " + mActiveTransitions.keySet());
- }
- if (active.mAnimations != null) {
- throw new IllegalStateException("Got a duplicate onTransitionReady call for "
- + transitionToken);
+ + transitionToken + ". expecting one of "
+ + Arrays.toString(mActiveTransitions.keySet().toArray()));
}
if (!info.getRootLeash().isValid()) {
// Invalid root-leash implies that the transition is empty/no-op, so just do
@@ -253,61 +251,39 @@
return;
}
}
-
- // No handler chose to perform this animation, so fall-back to the
- // default animation handling.
- final boolean isOpening = isOpeningType(info.getType());
- active.mAnimations = new ArrayList<>(); // Play fade animations
- for (int i = info.getChanges().size() - 1; i >= 0; --i) {
- final TransitionInfo.Change change = info.getChanges().get(i);
-
- // Don't animate anything with an animating parent
- if (change.getParent() != null) continue;
-
- final int mode = info.getChanges().get(i).getMode();
- if (isOpening && (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT)) {
- if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) {
- // This received a transferred starting window, so don't animate
- continue;
- }
- // fade in
- startExampleAnimation(transitionToken, change.getLeash(), true /* show */);
- } else if (!isOpening && (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK)) {
- // fade out
- startExampleAnimation(transitionToken, change.getLeash(), false /* show */);
- }
- }
- t.apply();
- onFinish(transitionToken);
+ throw new IllegalStateException(
+ "This shouldn't happen, maybe the default handler is broken.");
}
private void onFinish(IBinder transition) {
- final ActiveTransition active = mActiveTransitions.get(transition);
- if (active.mAnimations != null && !active.mAnimations.isEmpty()) return;
+ if (!mActiveTransitions.containsKey(transition)) {
+ Log.e(TAG, "Trying to finish a non-running transition. Maybe remote crashed?");
+ return;
+ }
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
"Transition animations finished, notifying core %s", transition);
mActiveTransitions.remove(transition);
mOrganizer.finishTransition(transition, null, null);
}
- private void requestStartTransition(int type, @NonNull IBinder transitionToken,
- @Nullable ActivityManager.RunningTaskInfo triggerTask) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition requested: type=%d %s",
- type, transitionToken);
-
+ void requestStartTransition(@NonNull IBinder transitionToken,
+ @Nullable TransitionRequestInfo request) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition requested: %s %s",
+ transitionToken, request);
if (mActiveTransitions.containsKey(transitionToken)) {
throw new RuntimeException("Transition already started " + transitionToken);
}
final ActiveTransition active = new ActiveTransition();
WindowContainerTransaction wct = null;
for (int i = mHandlers.size() - 1; i >= 0; --i) {
- wct = mHandlers.get(i).handleRequest(type, transitionToken, triggerTask);
+ wct = mHandlers.get(i).handleRequest(transitionToken, request);
if (wct != null) {
active.mFirstHandler = mHandlers.get(i);
break;
}
}
- IBinder transition = mOrganizer.startTransition(type, transitionToken, wct);
+ IBinder transition = mOrganizer.startTransition(
+ request.getType(), transitionToken, wct);
mActiveTransitions.put(transition, active);
}
@@ -330,6 +306,7 @@
* for a particular transition. Otherwise, it is only called if no other handler before
* it handled the transition.
*
+ * @param finishCallback Call this when finished. This MUST be called on main thread.
* @return true if transition was handled, false if not (falls-back to default).
*/
boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@@ -337,15 +314,15 @@
/**
* Potentially handles a startTransition request.
- * @param type The transition type
- * @param triggerTask The task which triggered this transition request.
- * @return WCT to apply with transition-start or null if this handler isn't handling
- * the request.
+ *
+ * @param transition The transition whose start is being requested.
+ * @param request Information about what is requested.
+ * @return WCT to apply with transition-start or null. If a WCT is returned here, this
+ * handler will be the first in line to animate.
*/
@Nullable
- WindowContainerTransaction handleRequest(@WindowManager.TransitionType int type,
- @NonNull IBinder transition,
- @Nullable ActivityManager.RunningTaskInfo triggerTask);
+ WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request);
}
@BinderThread
@@ -359,11 +336,9 @@
}
@Override
- public void requestStartTransition(int i, IBinder iBinder,
- ActivityManager.RunningTaskInfo runningTaskInfo) throws RemoteException {
- mMainExecutor.execute(() -> {
- Transitions.this.requestStartTransition(i, iBinder, runningTaskInfo);
- });
+ public void requestStartTransition(IBinder iBinder,
+ TransitionRequestInfo request) throws RemoteException {
+ mMainExecutor.execute(() -> Transitions.this.requestStartTransition(iBinder, request));
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 8543850..94c1f59 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -29,7 +29,7 @@
enabled: Boolean = bugId == 0
) {
end("appPairsDividerIsVisible", bugId, enabled) {
- this.showsLayer(FlickerTestBase.SPLIT_DIVIDER)
+ this.showsLayer(FlickerTestBase.APP_PAIR_SPLIT_DIVIDER)
}
}
@@ -39,7 +39,7 @@
enabled: Boolean = bugId == 0
) {
end("appPairsDividerIsInVisible", bugId, enabled) {
- this.hasNotLayer(FlickerTestBase.SPLIT_DIVIDER)
+ this.hasNotLayer(FlickerTestBase.APP_PAIR_SPLIT_DIVIDER)
}
}
@@ -109,7 +109,7 @@
end("PrimaryAppBounds", bugId, enabled) {
val entry = this.trace.entries.firstOrNull()
?: throw IllegalStateException("Trace is empty")
- val dividerRegion = entry.getVisibleBounds(FlickerTestBase.SPLIT_DIVIDER)
+ val dividerRegion = entry.getVisibleBounds(FlickerTestBase.APP_PAIR_SPLIT_DIVIDER)
this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -124,7 +124,7 @@
end("SecondaryAppBounds", bugId, enabled) {
val entry = this.trace.entries.firstOrNull()
?: throw IllegalStateException("Trace is empty")
- val dividerRegion = entry.getVisibleBounds(FlickerTestBase.SPLIT_DIVIDER)
+ val dividerRegion = entry.getVisibleBounds(FlickerTestBase.APP_PAIR_SPLIT_DIVIDER)
this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
index 7809be0..24e5fef 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
@@ -130,7 +130,7 @@
const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar"
const val STATUS_BAR_WINDOW_TITLE = "StatusBar"
const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
- const val SPLIT_DIVIDER = "SplitDivider"
+ const val APP_PAIR_SPLIT_DIVIDER = "AppPairSplitDivider"
const val IMAGE_WALLPAPER = "ImageWallpaper"
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
index 22b1eb7..cb9fabd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt
@@ -107,7 +107,7 @@
end("appsEndingBounds", enabled = false) {
val entry = this.trace.entries.firstOrNull()
?: throw IllegalStateException("Trace is empty")
- val dividerRegion = entry.getVisibleBounds(SPLIT_DIVIDER)
+ val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
this.hasVisibleRegion(primaryApp.defaultWindowName,
appPairsHelper.getPrimaryBounds(dividerRegion))
.and()
@@ -151,7 +151,7 @@
start("appsStartingBounds", enabled = false) {
val entry = this.trace.entries.firstOrNull()
?: throw IllegalStateException("Trace is empty")
- val dividerRegion = entry.getVisibleBounds(SPLIT_DIVIDER)
+ val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
this.hasVisibleRegion(primaryApp.defaultWindowName,
appPairsHelper.getPrimaryBounds(dividerRegion))
.and()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestRunningTaskInfoBuilder.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
similarity index 71%
rename from libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestRunningTaskInfoBuilder.java
rename to libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
index 76d3a6a..1f58a85 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestRunningTaskInfoBuilder.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
@@ -14,27 +14,37 @@
* limitations under the License.
*/
-package com.android.wm.shell.apppairs;
+package com.android.wm.shell;
+
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import android.app.ActivityManager;
import android.graphics.Rect;
import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;
-public class TestRunningTaskInfoBuilder {
+public final class TestRunningTaskInfoBuilder {
static int sNextTaskId = 500;
private Rect mBounds = new Rect(0, 0, 100, 100);
private WindowContainerToken mToken =
new WindowContainerToken(new IWindowContainerToken.Default());
+ private int mParentTaskId = INVALID_TASK_ID;
- TestRunningTaskInfoBuilder setBounds(Rect bounds) {
+ public TestRunningTaskInfoBuilder setBounds(Rect bounds) {
mBounds.set(bounds);
return this;
}
- ActivityManager.RunningTaskInfo build() {
+ public TestRunningTaskInfoBuilder setParentTaskId(int taskId) {
+ mParentTaskId = taskId;
+ return this;
+ }
+
+ public ActivityManager.RunningTaskInfo build() {
final ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
+ info.parentTaskId = INVALID_TASK_ID;
info.taskId = sNextTaskId++;
+ info.parentTaskId = mParentTaskId;
info.configuration.windowConfiguration.setBounds(mBounds);
info.token = mToken;
info.isResizeable = true;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestShellExecutor.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestShellExecutor.java
new file mode 100644
index 0000000..9eb13fb
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestShellExecutor.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell;
+
+import android.os.Looper;
+
+import com.android.wm.shell.common.ShellExecutor;
+
+import java.util.ArrayList;
+
+/**
+ * Really basic test executor. It just gathers all events in a blob. The only option is to
+ * execute everything at once. If better control over delayed execution is needed, please add it.
+ */
+public class TestShellExecutor implements ShellExecutor {
+ final ArrayList<Runnable> mRunnables = new ArrayList<>();
+
+ @Override
+ public void execute(Runnable runnable) {
+ mRunnables.add(runnable);
+ }
+
+ @Override
+ public void executeDelayed(Runnable r, long delayMillis) {
+ mRunnables.add(r);
+ }
+
+ @Override
+ public void removeCallbacks(Runnable r) {
+ mRunnables.remove(r);
+ }
+
+ @Override
+ public boolean hasCallback(Runnable r) {
+ return !mRunnables.isEmpty();
+ }
+
+ @Override
+ public Looper getLooper() {
+ return null;
+ }
+
+ public void flushAll() {
+ for (int i = mRunnables.size() - 1; i >= 0; --i) {
+ mRunnables.get(i).run();
+ }
+ mRunnables.clear();
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java
index 8dbc1d5..d21183e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairTests.java
@@ -32,6 +32,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SyncTransactionQueue;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairsControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairsControllerTests.java
index fada694..505c153 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairsControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/AppPairsControllerTests.java
@@ -32,6 +32,7 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.SyncTransactionQueue;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
index be09636..e094158 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java
@@ -16,16 +16,21 @@
package com.android.wm.shell.apppairs;
+import static org.mockito.Mockito.mock;
+
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
+import org.mockito.Mock;
+
public class TestAppPairsController extends AppPairsController {
- TestAppPairsPool mPool;
+ private TestAppPairsPool mPool;
public TestAppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
DisplayController displayController) {
- super(organizer, syncQueue, displayController);
+ super(organizer, syncQueue, displayController, mock(ShellExecutor.class));
mPool = new TestAppPairsPool(this);
setPairsPool(mPool);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsPool.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsPool.java
index 080f207..1ee7fff 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsPool.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsPool.java
@@ -18,6 +18,8 @@
import android.app.ActivityManager;
+import com.android.wm.shell.TestRunningTaskInfoBuilder;
+
public class TestAppPairsPool extends AppPairsPool{
TestAppPairsPool(AppPairsController controller) {
super(controller);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index cd46816..5821eed 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -55,6 +55,7 @@
public void setup() {
MockitoAnnotations.initMocks(this);
mSplitLayout = new SplitLayout(
+ "TestSplitLayout",
mContext,
getConfiguration(false),
mLayoutChangeListener,
@@ -64,6 +65,7 @@
@Test
@UiThreadTest
public void testUpdateConfiguration() {
+ mSplitLayout.init();
assertThat(mSplitLayout.updateConfiguration(getConfiguration(false))).isFalse();
assertThat(mSplitLayout.updateConfiguration(getConfiguration(true))).isTrue();
}
@@ -81,6 +83,12 @@
}
@Test
+ public void testOnDoubleTappedDivider() {
+ mSplitLayout.onDoubleTappedDivider();
+ verify(mLayoutChangeListener).onDoubleTappedDivider();
+ }
+
+ @Test
@UiThreadTest
public void testSnapToDismissTarget() {
// verify it callbacks properly when the snap target indicates dismissing split.
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index c170563..698315a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -49,7 +49,7 @@
MockitoAnnotations.initMocks(this);
final Configuration configuration = new Configuration();
configuration.setToDefaults();
- mSplitWindowManager = new SplitWindowManager(mContext, configuration,
+ mSplitWindowManager = new SplitWindowManager("TestSplitDivider", mContext, configuration,
b -> b.setParent(mSurfaceControl));
when(mSplitLayout.getDividerBounds()).thenReturn(
new Rect(0, 0, configuration.windowConfiguration.getBounds().width(),
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
new file mode 100644
index 0000000..702e894
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.ActivityManager;
+import android.view.SurfaceControl;
+import android.window.WindowContainerTransaction;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+/** Tests for {@link MainStage} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MainStageTests {
+ @Mock private ShellTaskOrganizer mTaskOrganizer;
+ @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
+ @Mock private SyncTransactionQueue mSyncQueue;
+ @Mock private ActivityManager.RunningTaskInfo mRootTaskInfo;
+ @Mock private SurfaceControl mRootLeash;
+ @Spy private WindowContainerTransaction mWct;
+ private MainStage mMainStage;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
+ mMainStage = new MainStage(mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, mSyncQueue);
+ mMainStage.onTaskAppeared(mRootTaskInfo, mRootLeash);
+ }
+
+ @Test
+ public void testActiveDeactivate() {
+ mMainStage.activate(mRootTaskInfo.configuration.windowConfiguration.getBounds(), mWct);
+ assertThat(mMainStage.isActive()).isTrue();
+
+ mMainStage.deactivate(mWct);
+ assertThat(mMainStage.isActive()).isFalse();
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
new file mode 100644
index 0000000..01888b7
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.view.SurfaceControl;
+import android.window.WindowContainerTransaction;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+
+/** Tests for {@link SideStage} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SideStageTests {
+ @Mock private ShellTaskOrganizer mTaskOrganizer;
+ @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
+ @Mock private SyncTransactionQueue mSyncQueue;
+ @Mock private ActivityManager.RunningTaskInfo mRootTask;
+ @Mock private SurfaceControl mRootLeash;
+ @Spy private WindowContainerTransaction mWct;
+ private SideStage mSideStage;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mRootTask = new TestRunningTaskInfoBuilder().build();
+ mSideStage = new SideStage(mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, mSyncQueue);
+ mSideStage.onTaskAppeared(mRootTask, mRootLeash);
+ }
+
+ @Test
+ public void testAddTask() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+
+ mSideStage.addTask(task, mRootTask.configuration.windowConfiguration.getBounds(), mWct);
+
+ verify(mWct).reparent(eq(task.token), eq(mRootTask.token), eq(true));
+ }
+
+ @Test
+ public void testRemoveTask() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+ assertThat(mSideStage.removeTask(task.taskId, null, mWct)).isFalse();
+
+ mSideStage.mChildrenTaskInfo.put(task.taskId, task);
+ assertThat(mSideStage.removeTask(task.taskId, null, mWct)).isTrue();
+ verify(mWct).reparent(eq(task.token), isNull(), eq(false));
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
new file mode 100644
index 0000000..168e0df
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
+
+import static com.android.wm.shell.splitscreen.SplitScreen.SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.graphics.Rect;
+import android.window.DisplayAreaInfo;
+import android.window.IWindowContainerToken;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Tests for {@link StageCoordinator} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class StageCoordinatorTests extends ShellTestCase {
+ @Mock private ShellTaskOrganizer mTaskOrganizer;
+ @Mock private SyncTransactionQueue mSyncQueue;
+ @Mock private RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
+ @Mock private MainStage mMainStage;
+ @Mock private SideStage mSideStage;
+ private StageCoordinator mStageCoordinator;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mStageCoordinator = new TestStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
+ mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage);
+ }
+
+ @Test
+ public void testMoveToSideStage() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+
+ mStageCoordinator.moveToSideStage(task, SIDE_STAGE_POSITION_BOTTOM_OR_RIGHT);
+
+ verify(mMainStage).activate(any(Rect.class), any(WindowContainerTransaction.class));
+ verify(mSideStage).addTask(eq(task), any(Rect.class),
+ any(WindowContainerTransaction.class));
+ }
+
+ @Test
+ public void testRemoveFromSideStage() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+
+ doReturn(false).when(mMainStage).isActive();
+ mStageCoordinator.removeFromSideStage(task.taskId);
+
+ verify(mSideStage).removeTask(
+ eq(task.taskId), any(), any(WindowContainerTransaction.class));
+ }
+
+ private static class TestStageCoordinator extends StageCoordinator {
+ final DisplayAreaInfo mDisplayAreaInfo;
+
+ TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
+ RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
+ MainStage mainStage, SideStage sideStage) {
+ super(context, displayId, syncQueue, rootTDAOrganizer, taskOrganizer, mainStage,
+ sideStage);
+
+ // Prepare default TaskDisplayArea for testing.
+ mDisplayAreaInfo = new DisplayAreaInfo(
+ new WindowContainerToken(new IWindowContainerToken.Default()),
+ DEFAULT_DISPLAY,
+ FEATURE_DEFAULT_TASK_CONTAINER);
+ this.onDisplayAreaAppeared(mDisplayAreaInfo);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
new file mode 100644
index 0000000..c66e073
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.splitscreen;
+
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.view.SurfaceControl;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.TestRunningTaskInfoBuilder;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Tests for {@link StageTaskListener} */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class StageTaskListenerTests {
+ @Mock private ShellTaskOrganizer mTaskOrganizer;
+ @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
+ @Mock private SyncTransactionQueue mSyncQueue;
+ private ActivityManager.RunningTaskInfo mRootTask;
+ private StageTaskListener mStageTaskListener;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mStageTaskListener = new StageTaskListener(
+ mTaskOrganizer,
+ DEFAULT_DISPLAY,
+ mCallbacks,
+ mSyncQueue);
+ mRootTask = new TestRunningTaskInfoBuilder().build();
+ mRootTask.parentTaskId = INVALID_TASK_ID;
+ mStageTaskListener.onTaskAppeared(mRootTask, new SurfaceControl());
+ }
+
+ @Test
+ public void testRootTaskAppeared() {
+ assertThat(mStageTaskListener.mRootTaskInfo.taskId).isEqualTo(mRootTask.taskId);
+ verify(mCallbacks).onRootTaskAppeared();
+ verify(mCallbacks).onStatusChanged(eq(mRootTask.isVisible), eq(false));
+ }
+
+ @Test
+ public void testChildTaskAppeared() {
+ final ActivityManager.RunningTaskInfo childTask =
+ new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build();
+
+ mStageTaskListener.onTaskAppeared(childTask, new SurfaceControl());
+
+ assertThat(mStageTaskListener.mChildrenTaskInfo.contains(childTask.taskId)).isTrue();
+ verify(mCallbacks).onStatusChanged(eq(mRootTask.isVisible), eq(true));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testUnknownTaskVanished() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+ mStageTaskListener.onTaskVanished(task);
+ }
+
+ @Test
+ public void testTaskVanished() {
+ final ActivityManager.RunningTaskInfo childTask =
+ new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build();
+ mStageTaskListener.mRootTaskInfo = mRootTask;
+ mStageTaskListener.mChildrenTaskInfo.put(childTask.taskId, childTask);
+
+ mStageTaskListener.onTaskVanished(childTask);
+ verify(mCallbacks, times(2)).onStatusChanged(eq(mRootTask.isVisible), eq(false));
+
+ mStageTaskListener.onTaskVanished(mRootTask);
+ verify(mCallbacks).onRootTaskVanished();
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
new file mode 100644
index 0000000..f3bee4b
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.transition;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
+import android.window.IRemoteTransition;
+import android.window.TransitionFilter;
+import android.window.TransitionInfo;
+import android.window.TransitionRequestInfo;
+import android.window.WindowContainerTransaction;
+import android.window.WindowOrganizer;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.TestShellExecutor;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TransactionPool;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+/**
+ * Tests for the shell transitions.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ShellTransitionTests {
+
+ private final WindowOrganizer mOrganizer = mock(WindowOrganizer.class);
+ private final TransactionPool mTransactionPool = mock(TransactionPool.class);
+ private final TestShellExecutor mMainExecutor = new TestShellExecutor();
+ private final ShellExecutor mAnimExecutor = new TestShellExecutor();
+ private final TestTransitionHandler mDefaultHandler = new TestTransitionHandler();
+
+ @Before
+ public void setUp() {
+ doAnswer(invocation -> invocation.getArguments()[1])
+ .when(mOrganizer).startTransition(anyInt(), any(), any());
+ }
+
+ @Test
+ public void testBasicTransitionFlow() {
+ Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
+ mAnimExecutor);
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ IBinder transitToken = new Binder();
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+ verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), any());
+ TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken, info, mock(SurfaceControl.Transaction.class));
+ assertEquals(1, mDefaultHandler.activeCount());
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken), any(), any());
+ }
+
+ @Test
+ public void testNonDefaultHandler() {
+ Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
+ mAnimExecutor);
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ final WindowContainerTransaction handlerWCT = new WindowContainerTransaction();
+ // Make a test handler that only responds to multi-window triggers AND only animates
+ // Change transitions.
+ TestTransitionHandler testHandler = new TestTransitionHandler() {
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {
+ for (TransitionInfo.Change chg : info.getChanges()) {
+ if (chg.getMode() == TRANSIT_CHANGE) {
+ return super.startAnimation(transition, info, t, finishCallback);
+ }
+ }
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ final RunningTaskInfo task = request.getTriggerTask();
+ return (task != null && task.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW)
+ ? handlerWCT : null;
+ }
+ };
+ transitions.addHandler(testHandler);
+
+ IBinder transitToken = new Binder();
+ TransitionInfo open = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+
+ // Make a request that will be rejected by the testhandler.
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+ verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), isNull());
+ transitions.onTransitionReady(transitToken, open, mock(SurfaceControl.Transaction.class));
+ assertEquals(1, mDefaultHandler.activeCount());
+ assertEquals(0, testHandler.activeCount());
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+
+ // Make a request that will be handled by testhandler but not animated by it.
+ RunningTaskInfo mwTaskInfo =
+ createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, mwTaskInfo, null /* remote */));
+ verify(mOrganizer, times(1)).startTransition(
+ eq(TRANSIT_OPEN), eq(transitToken), eq(handlerWCT));
+ transitions.onTransitionReady(transitToken, open, mock(SurfaceControl.Transaction.class));
+ assertEquals(1, mDefaultHandler.activeCount());
+ assertEquals(0, testHandler.activeCount());
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+
+ // Make a request that will be handled AND animated by testhandler.
+ // Add an aggressive handler (doesn't handle but always animates) on top to make sure that
+ // the test handler gets first shot at animating since it claimed to handle it.
+ TestTransitionHandler topHandler = new TestTransitionHandler();
+ transitions.addHandler(topHandler);
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_CHANGE, mwTaskInfo, null /* remote */));
+ verify(mOrganizer, times(1)).startTransition(
+ eq(TRANSIT_CHANGE), eq(transitToken), eq(handlerWCT));
+ TransitionInfo change = new TransitionInfoBuilder(TRANSIT_CHANGE)
+ .addChange(TRANSIT_CHANGE).build();
+ transitions.onTransitionReady(transitToken, change, mock(SurfaceControl.Transaction.class));
+ assertEquals(0, mDefaultHandler.activeCount());
+ assertEquals(1, testHandler.activeCount());
+ assertEquals(0, topHandler.activeCount());
+ testHandler.finishAll();
+ mMainExecutor.flushAll();
+ }
+
+ @Test
+ public void testRequestRemoteTransition() {
+ Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
+ mAnimExecutor);
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ final boolean[] remoteCalled = new boolean[]{false};
+ IRemoteTransition testRemote = new IRemoteTransition.Stub() {
+ @Override
+ public void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
+ IRemoteAnimationFinishedCallback finishCallback) throws RemoteException {
+ remoteCalled[0] = true;
+ finishCallback.onAnimationFinished();
+ }
+ };
+ IBinder transitToken = new Binder();
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, testRemote));
+ verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), any());
+ TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken, info, mock(SurfaceControl.Transaction.class));
+ assertEquals(0, mDefaultHandler.activeCount());
+ assertTrue(remoteCalled[0]);
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken), any(), any());
+ }
+
+ @Test
+ public void testTransitionFilterActivityType() {
+ TransitionFilter filter = new TransitionFilter();
+ filter.mRequirements =
+ new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()};
+ filter.mRequirements[0].mActivityType = ACTIVITY_TYPE_HOME;
+ filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+
+ final TransitionInfo openHome = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN,
+ createTaskInfo(1, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME)).build();
+ assertTrue(filter.matches(openHome));
+
+ final TransitionInfo openStd = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN, createTaskInfo(
+ 1, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD)).build();
+ assertFalse(filter.matches(openStd));
+ }
+
+ @Test
+ public void testTransitionFilterMultiRequirement() {
+ // filter that requires at-least one opening and one closing app
+ TransitionFilter filter = new TransitionFilter();
+ filter.mRequirements = new TransitionFilter.Requirement[]{
+ new TransitionFilter.Requirement(), new TransitionFilter.Requirement()};
+ filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+ filter.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
+
+ final TransitionInfo openOnly = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).build();
+ assertFalse(filter.matches(openOnly));
+
+ final TransitionInfo openClose = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ assertTrue(filter.matches(openClose));
+ }
+
+ @Test
+ public void testRegisteredRemoteTransition() {
+ Transitions transitions = new Transitions(mOrganizer, mTransactionPool, mMainExecutor,
+ mAnimExecutor);
+ transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+ final boolean[] remoteCalled = new boolean[]{false};
+ IRemoteTransition testRemote = new IRemoteTransition.Stub() {
+ @Override
+ public void startAnimation(TransitionInfo info, SurfaceControl.Transaction t,
+ IRemoteAnimationFinishedCallback finishCallback) throws RemoteException {
+ remoteCalled[0] = true;
+ finishCallback.onAnimationFinished();
+ }
+ };
+
+ TransitionFilter filter = new TransitionFilter();
+ filter.mRequirements =
+ new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()};
+ filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+
+ transitions.registerRemote(filter, testRemote);
+ mMainExecutor.flushAll();
+
+ IBinder transitToken = new Binder();
+ transitions.requestStartTransition(transitToken,
+ new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+ verify(mOrganizer, times(1)).startTransition(eq(TRANSIT_OPEN), eq(transitToken), any());
+ TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
+ .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+ transitions.onTransitionReady(transitToken, info, mock(SurfaceControl.Transaction.class));
+ assertEquals(0, mDefaultHandler.activeCount());
+ assertTrue(remoteCalled[0]);
+ mDefaultHandler.finishAll();
+ mMainExecutor.flushAll();
+ verify(mOrganizer, times(1)).finishTransition(eq(transitToken), any(), any());
+ }
+
+ class TransitionInfoBuilder {
+ final TransitionInfo mInfo;
+
+ TransitionInfoBuilder(@WindowManager.TransitionType int type) {
+ mInfo = new TransitionInfo(type, 0 /* flags */);
+ mInfo.setRootLeash(createMockSurface(true /* valid */), 0, 0);
+ }
+
+ TransitionInfoBuilder addChange(@WindowManager.TransitionType int mode,
+ RunningTaskInfo taskInfo) {
+ final TransitionInfo.Change change =
+ new TransitionInfo.Change(null /* token */, null /* leash */);
+ change.setMode(mode);
+ change.setTaskInfo(taskInfo);
+ mInfo.addChange(change);
+ return this;
+ }
+
+ TransitionInfoBuilder addChange(@WindowManager.TransitionType int mode) {
+ return addChange(mode, null /* taskInfo */);
+ }
+
+ TransitionInfo build() {
+ return mInfo;
+ }
+ }
+
+ class TestTransitionHandler implements Transitions.TransitionHandler {
+ final ArrayList<Runnable> mFinishes = new ArrayList<>();
+
+ @Override
+ public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+ @NonNull SurfaceControl.Transaction t, @NonNull Runnable finishCallback) {
+ mFinishes.add(finishCallback);
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
+ @NonNull TransitionRequestInfo request) {
+ return null;
+ }
+
+ void finishAll() {
+ for (int i = mFinishes.size() - 1; i >= 0; --i) {
+ mFinishes.get(i).run();
+ }
+ mFinishes.clear();
+ }
+
+ int activeCount() {
+ return mFinishes.size();
+ }
+ }
+
+ private static SurfaceControl createMockSurface(boolean valid) {
+ SurfaceControl sc = mock(SurfaceControl.class);
+ doReturn(valid).when(sc).isValid();
+ return sc;
+ }
+
+ private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode, int activityType) {
+ RunningTaskInfo taskInfo = new RunningTaskInfo();
+ taskInfo.taskId = taskId;
+ taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
+ taskInfo.configuration.windowConfiguration.setActivityType(activityType);
+ return taskInfo;
+ }
+
+ private static RunningTaskInfo createTaskInfo(int taskId) {
+ RunningTaskInfo taskInfo = new RunningTaskInfo();
+ taskInfo.taskId = taskId;
+ return taskInfo;
+ }
+
+}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 3f06000..03ab62f 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -103,10 +103,10 @@
}
bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets,
- bool invalidate_caches, bool filter_incompatible_configs) {
+ bool invalidate_caches) {
apk_assets_ = apk_assets;
BuildDynamicRefTable();
- RebuildFilterList(filter_incompatible_configs);
+ RebuildFilterList();
if (invalidate_caches) {
InvalidateCaches(static_cast<uint32_t>(-1));
}
@@ -623,7 +623,8 @@
if (UNLIKELY(logging_enabled)) {
last_resolution_.steps.push_back(
Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->config.toString(),
- overlay_result->package_name});
+ overlay_result->package_name,
+ overlay_result->cookie});
}
}
}
@@ -646,22 +647,21 @@
const LoadedPackage* best_package = nullptr;
incfs::verified_map_ptr<ResTable_type> best_type;
const ResTable_config* best_config = nullptr;
- ResTable_config best_config_copy;
uint32_t best_offset = 0U;
uint32_t type_flags = 0U;
- auto resolution_type = Resolution::Step::Type::NO_ENTRY;
std::vector<Resolution::Step> resolution_steps;
- // If desired_config is the same as the set configuration, then we can use our filtered list
- // and we don't need to match the configurations, since they already matched.
- const bool use_fast_path = !ignore_configuration && &desired_config == &configuration_;
+ // If `desired_config` is not the same as the set configuration or the caller will accept a value
+ // from any configuration, then we cannot use our filtered list of types since it only it contains
+ // types matched to the set configuration.
+ const bool use_filtered = !ignore_configuration && &desired_config == &configuration_;
const size_t package_count = package_group.packages_.size();
for (size_t pi = 0; pi < package_count; pi++) {
const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi];
const LoadedPackage* loaded_package = loaded_package_impl.loaded_package_;
- ApkAssetsCookie cookie = package_group.cookies_[pi];
+ const ApkAssetsCookie cookie = package_group.cookies_[pi];
// If the type IDs are offset in this package, we need to take that into account when searching
// for a type.
@@ -670,130 +670,82 @@
continue;
}
+ // Allow custom loader packages to overlay resource values with configurations equivalent to the
+ // current best configuration.
+ const bool package_is_loader = loaded_package->IsCustomLoader();
+
auto entry_flags = type_spec->GetFlagsForEntryIndex(entry_idx);
if (UNLIKELY(!entry_flags.has_value())) {
return base::unexpected(entry_flags.error());
}
type_flags |= entry_flags.value();
- // If the package is an overlay or custom loader,
- // then even configurations that are the same MUST be chosen.
- const bool package_is_loader = loaded_package->IsCustomLoader();
+ const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
+ const size_t type_entry_count = (use_filtered) ? filtered_group.type_entries.size()
+ : type_spec->type_entries.size();
+ for (size_t i = 0; i < type_entry_count; i++) {
+ const TypeSpec::TypeEntry* type_entry = (use_filtered) ? filtered_group.type_entries[i]
+ : &type_spec->type_entries[i];
- if (use_fast_path) {
- const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
- for (const auto& type_config : filtered_group.type_configs) {
- const ResTable_config& this_config = type_config.config;
-
- // We can skip calling ResTable_config::match() because we know that all candidate
- // configurations that do NOT match have been filtered-out.
- if (best_config == nullptr) {
- resolution_type = Resolution::Step::Type::INITIAL;
- } else if (this_config.isBetterThan(*best_config, &desired_config)) {
- resolution_type = (package_is_loader) ? Resolution::Step::Type::BETTER_MATCH_LOADER
- : Resolution::Step::Type::BETTER_MATCH;
- } else if (package_is_loader && this_config.compare(*best_config) == 0) {
- resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
- } else {
- if (UNLIKELY(logging_enabled)) {
- resolution_type = (package_is_loader) ? Resolution::Step::Type::SKIPPED_LOADER
- : Resolution::Step::Type::SKIPPED;
- resolution_steps.push_back(Resolution::Step{resolution_type,
- this_config.toString(),
- &loaded_package->GetPackageName()});
- }
- continue;
- }
-
- // The configuration matches and is better than the previous selection.
- // Find the entry value if it exists for this configuration.
- const auto& type = type_config.type;
- const auto offset = LoadedPackage::GetEntryOffset(type, entry_idx);
- if (UNLIKELY(IsIOError(offset))) {
- return base::unexpected(offset.error());
- }
- if (!offset.has_value()) {
- if (UNLIKELY(logging_enabled)) {
- if (package_is_loader) {
- resolution_type = Resolution::Step::Type::NO_ENTRY_LOADER;
- } else {
- resolution_type = Resolution::Step::Type::NO_ENTRY;
- }
- resolution_steps.push_back(Resolution::Step{resolution_type,
- this_config.toString(),
- &loaded_package->GetPackageName()});
- }
- continue;
- }
-
- best_cookie = cookie;
- best_package = loaded_package;
- best_type = type;
- best_config = &this_config;
- best_offset = offset.value();
-
- if (UNLIKELY(logging_enabled)) {
- last_resolution_.steps.push_back(Resolution::Step{resolution_type,
- this_config.toString(),
- &loaded_package->GetPackageName()});
- }
+ // We can skip calling ResTable_config::match() if the caller does not care for the
+ // configuration to match or if we're using the list of types that have already had their
+ // configuration matched.
+ const ResTable_config& this_config = type_entry->config;
+ if (!(use_filtered || ignore_configuration || this_config.match(desired_config))) {
+ continue;
}
- } else {
- // This is the slower path, which doesn't use the filtered list of configurations.
- // Here we must read the ResTable_config from the mmapped APK, convert it to host endianness
- // and fill in any new fields that did not exist when the APK was compiled.
- // Furthermore when selecting configurations we can't just record the pointer to the
- // ResTable_config, we must copy it.
- const auto iter_end = type_spec->types + type_spec->type_count;
- for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- const incfs::verified_map_ptr<ResTable_type>& type = *iter;
- ResTable_config this_config{};
- if (!ignore_configuration) {
- this_config.copyFromDtoH(type->config);
- if (!this_config.match(desired_config)) {
- continue;
- }
-
- if (best_config == nullptr) {
- resolution_type = Resolution::Step::Type::INITIAL;
- } else if (this_config.isBetterThan(*best_config, &desired_config)) {
- resolution_type = (package_is_loader) ? Resolution::Step::Type::BETTER_MATCH_LOADER
- : Resolution::Step::Type::BETTER_MATCH;
- } else if (package_is_loader && this_config.compare(*best_config) == 0) {
- resolution_type = Resolution::Step::Type::OVERLAID_LOADER;
- } else {
- continue;
- }
- }
-
- // The configuration matches and is better than the previous selection.
- // Find the entry value if it exists for this configuration.
- const auto offset = LoadedPackage::GetEntryOffset(type, entry_idx);
- if (UNLIKELY(IsIOError(offset))) {
- return base::unexpected(offset.error());
- }
- if (!offset.has_value()) {
- continue;
- }
-
- best_cookie = cookie;
- best_package = loaded_package;
- best_type = type;
- best_config_copy = this_config;
- best_config = &best_config_copy;
- best_offset = offset.value();
-
- if (stop_at_first_match) {
- // Any configuration will suffice, so break.
- break;
- }
-
+ Resolution::Step::Type resolution_type;
+ if (best_config == nullptr) {
+ resolution_type = Resolution::Step::Type::INITIAL;
+ } else if (this_config.isBetterThan(*best_config, &desired_config)) {
+ resolution_type = Resolution::Step::Type::BETTER_MATCH;
+ } else if (package_is_loader && this_config.compare(*best_config) == 0) {
+ resolution_type = Resolution::Step::Type::OVERLAID;
+ } else {
if (UNLIKELY(logging_enabled)) {
- last_resolution_.steps.push_back(Resolution::Step{resolution_type,
- this_config.toString(),
- &loaded_package->GetPackageName()});
+ resolution_steps.push_back(Resolution::Step{Resolution::Step::Type::SKIPPED,
+ this_config.toString(),
+ &loaded_package->GetPackageName(),
+ cookie});
}
+ continue;
+ }
+
+ // The configuration matches and is better than the previous selection.
+ // Find the entry value if it exists for this configuration.
+ const auto& type = type_entry->type;
+ const auto offset = LoadedPackage::GetEntryOffset(type, entry_idx);
+ if (UNLIKELY(IsIOError(offset))) {
+ return base::unexpected(offset.error());
+ }
+
+ if (!offset.has_value()) {
+ if (UNLIKELY(logging_enabled)) {
+ resolution_steps.push_back(Resolution::Step{Resolution::Step::Type::NO_ENTRY,
+ this_config.toString(),
+ &loaded_package->GetPackageName(),
+ cookie});
+ }
+ continue;
+ }
+
+ best_cookie = cookie;
+ best_package = loaded_package;
+ best_type = type;
+ best_config = &this_config;
+ best_offset = offset.value();
+
+ if (UNLIKELY(logging_enabled)) {
+ last_resolution_.steps.push_back(Resolution::Step{resolution_type,
+ this_config.toString(),
+ &loaded_package->GetPackageName(),
+ cookie});
+ }
+
+ // Any configuration will suffice, so break.
+ if (stop_at_first_match) {
+ break;
}
}
}
@@ -851,19 +803,16 @@
return {};
}
- auto cookie = last_resolution_.cookie;
+ const ApkAssetsCookie cookie = last_resolution_.cookie;
if (cookie == kInvalidCookie) {
LOG(ERROR) << "AssetManager hasn't resolved a resource to read resolution path.";
return {};
}
- uint32_t resid = last_resolution_.resid;
- std::vector<Resolution::Step>& steps = last_resolution_.steps;
+ const uint32_t resid = last_resolution_.resid;
+ const auto package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
+
std::string resource_name_string;
-
- const LoadedPackage* package =
- apk_assets_[cookie]->GetLoadedArsc()->GetPackageById(get_package_id(resid));
-
if (package != nullptr) {
auto resource_name = ToResourceName(last_resolution_.type_string_ref,
last_resolution_.entry_string_ref,
@@ -878,44 +827,24 @@
<< "\n\tFor config -"
<< configuration_.toString();
- std::string prefix;
- for (Resolution::Step step : steps) {
- switch (step.type) {
- case Resolution::Step::Type::INITIAL:
- prefix = "Found initial";
- break;
- case Resolution::Step::Type::BETTER_MATCH:
- prefix = "Found better";
- break;
- case Resolution::Step::Type::BETTER_MATCH_LOADER:
- prefix = "Found better in loader";
- break;
- case Resolution::Step::Type::OVERLAID:
- prefix = "Overlaid";
- break;
- case Resolution::Step::Type::OVERLAID_LOADER:
- prefix = "Overlaid by loader";
- break;
- case Resolution::Step::Type::SKIPPED:
- prefix = "Skipped";
- break;
- case Resolution::Step::Type::SKIPPED_LOADER:
- prefix = "Skipped loader";
- break;
- case Resolution::Step::Type::NO_ENTRY:
- prefix = "No entry";
- break;
- case Resolution::Step::Type::NO_ENTRY_LOADER:
- prefix = "No entry for loader";
- break;
+ for (const Resolution::Step& step : last_resolution_.steps) {
+ const static std::unordered_map<Resolution::Step::Type, const char*> kStepStrings = {
+ {Resolution::Step::Type::INITIAL, "Found initial"},
+ {Resolution::Step::Type::BETTER_MATCH, "Found better"},
+ {Resolution::Step::Type::OVERLAID, "Overlaid"},
+ {Resolution::Step::Type::SKIPPED, "Skipped"},
+ {Resolution::Step::Type::NO_ENTRY, "No entry"}
+ };
+
+ const auto prefix = kStepStrings.find(step.type);
+ if (prefix == kStepStrings.end()) {
+ continue;
}
- if (!prefix.empty()) {
- log_stream << "\n\t" << prefix << ": " << *step.package_name;
-
- if (!step.config_name.isEmpty()) {
- log_stream << " -" << step.config_name;
- }
+ log_stream << "\n\t" << prefix->second << ": " << *step.package_name << " ("
+ << apk_assets_[step.cookie]->GetPath() << ")";
+ if (!step.config_name.isEmpty()) {
+ log_stream << " -" << step.config_name;
}
}
@@ -935,6 +864,16 @@
*result->package_name);
}
+base::expected<uint32_t, NullOrIOError> AssetManager2::GetResourceTypeSpecFlags(
+ uint32_t resid) const {
+ auto result = FindEntry(resid, 0u /* density_override */, false /* stop_at_first_match */,
+ true /* ignore_configuration */);
+ if (!result.has_value()) {
+ return base::unexpected(result.error());
+ }
+ return result->type_flags;
+}
+
base::expected<AssetManager2::SelectedValue, NullOrIOError> AssetManager2::GetResource(
uint32_t resid, bool may_be_bag, uint16_t density_override) const {
auto result = FindEntry(resid, density_override, false /* stop_at_first_match */,
@@ -1333,7 +1272,7 @@
return base::unexpected(std::nullopt);
}
-void AssetManager2::RebuildFilterList(bool filter_incompatible_configs) {
+void AssetManager2::RebuildFilterList() {
for (PackageGroup& group : package_groups_) {
for (ConfiguredPackage& impl : group.packages_) {
// Destroy it.
@@ -1343,14 +1282,11 @@
new (&impl.filtered_configs_) ByteBucketArray<FilteredConfigGroup>();
// Create the filters here.
- impl.loaded_package_->ForEachTypeSpec([&](const TypeSpec* spec, uint8_t type_index) {
- FilteredConfigGroup& group = impl.filtered_configs_.editItemAt(type_index);
- const auto iter_end = spec->types + spec->type_count;
- for (auto iter = spec->types; iter != iter_end; ++iter) {
- ResTable_config this_config;
- this_config.copyFromDtoH((*iter)->config);
- if (!filter_incompatible_configs || this_config.match(configuration_)) {
- group.type_configs.push_back(TypeConfig{*iter, this_config});
+ impl.loaded_package_->ForEachTypeSpec([&](const TypeSpec& type_spec, uint8_t type_id) {
+ FilteredConfigGroup& group = impl.filtered_configs_.editItemAt(type_id - 1);
+ for (const auto& type_entry : type_spec.type_entries) {
+ if (type_entry.config.match(configuration_)) {
+ group.type_entries.push_back(&type_entry);
}
}
});
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 73e040c..adb383f95 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -326,6 +326,11 @@
}
}
+ if (data_size != 0) {
+ LOG(ERROR) << "idmap parsed with " << data_size << "bytes remaining";
+ return {};
+ }
+
// Can't use make_unique because LoadedIdmap constructor is private.
return std::unique_ptr<LoadedIdmap>(
new LoadedIdmap(idmap_path.to_string(), header, data_header, target_entries,
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 2fc3b05..996b424 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -33,7 +33,6 @@
#endif
#endif
-#include "androidfw/ByteBucketArray.h"
#include "androidfw/Chunk.h"
#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"
@@ -49,36 +48,24 @@
// Builder that helps accumulate Type structs and then create a single
// contiguous block of memory to store both the TypeSpec struct and
// the Type structs.
-class TypeSpecPtrBuilder {
- public:
- explicit TypeSpecPtrBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header)
- : header_(header) {
- }
+struct TypeSpecBuilder {
+ explicit TypeSpecBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header) : header_(header) {}
void AddType(incfs::verified_map_ptr<ResTable_type> type) {
- types_.push_back(type);
+ TypeSpec::TypeEntry& entry = type_entries.emplace_back();
+ entry.config.copyFromDtoH(type->config);
+ entry.type = type;
}
- TypeSpecPtr Build() {
- // Check for overflow.
- using ElementType = incfs::verified_map_ptr<ResTable_type>;
- if ((std::numeric_limits<size_t>::max() - sizeof(TypeSpec)) / sizeof(ElementType) <
- types_.size()) {
- return {};
- }
- TypeSpec* type_spec =
- (TypeSpec*)::malloc(sizeof(TypeSpec) + (types_.size() * sizeof(ElementType)));
- type_spec->type_spec = header_;
- type_spec->type_count = types_.size();
- memcpy(type_spec + 1, types_.data(), types_.size() * sizeof(ElementType));
- return TypeSpecPtr(type_spec);
+ TypeSpec Build() {
+ return {header_, std::move(type_entries)};
}
private:
- DISALLOW_COPY_AND_ASSIGN(TypeSpecPtrBuilder);
+ DISALLOW_COPY_AND_ASSIGN(TypeSpecBuilder);
incfs::verified_map_ptr<ResTable_typeSpec> header_;
- std::vector<incfs::verified_map_ptr<ResTable_type>> types_;
+ std::vector<TypeSpec::TypeEntry> type_entries;
};
} // namespace
@@ -322,15 +309,10 @@
}
base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations(
- bool exclude_mipmap, std::set<ResTable_config>* out_configs) const {
- const size_t type_count = type_specs_.size();
- for (size_t i = 0; i < type_count; i++) {
- const TypeSpecPtr& type_spec = type_specs_[i];
- if (type_spec == nullptr) {
- continue;
- }
+ bool exclude_mipmap, std::set<ResTable_config>* out_configs) const {\
+ for (const auto& type_spec : type_specs_) {
if (exclude_mipmap) {
- const int type_idx = type_spec->type_spec->id - 1;
+ const int type_idx = type_spec.first - 1;
const auto type_name16 = type_string_pool_.stringAt(type_idx);
if (UNLIKELY(IsIOError(type_name16))) {
return base::unexpected(GetIOError(type_name16.error()));
@@ -354,11 +336,8 @@
}
}
- const auto iter_end = type_spec->types + type_spec->type_count;
- for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- ResTable_config config;
- config.copyFromDtoH((*iter)->config);
- out_configs->insert(config);
+ for (const auto& type_entry : type_spec.second.type_entries) {
+ out_configs->insert(type_entry.config);
}
}
return {};
@@ -366,19 +345,12 @@
void LoadedPackage::CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const {
char temp_locale[RESTABLE_MAX_LOCALE_LEN];
- const size_t type_count = type_specs_.size();
- for (size_t i = 0; i < type_count; i++) {
- const TypeSpecPtr& type_spec = type_specs_[i];
- if (type_spec != nullptr) {
- const auto iter_end = type_spec->types + type_spec->type_count;
- for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- ResTable_config configuration;
- configuration.copyFromDtoH((*iter)->config);
- if (configuration.locale != 0) {
- configuration.getBcp47Locale(temp_locale, canonicalize);
- std::string locale(temp_locale);
- out_locales->insert(std::move(locale));
- }
+ for (const auto& type_spec : type_specs_) {
+ for (const auto& type_entry : type_spec.second.type_entries) {
+ if (type_entry.config.locale != 0) {
+ type_entry.config.getBcp47Locale(temp_locale, canonicalize);
+ std::string locale(temp_locale);
+ out_locales->insert(std::move(locale));
}
}
}
@@ -398,14 +370,13 @@
return base::unexpected(key_idx.error());
}
- const TypeSpec* type_spec = type_specs_[*type_idx].get();
+ const TypeSpec* type_spec = GetTypeSpecByTypeIndex(*type_idx);
if (type_spec == nullptr) {
return base::unexpected(std::nullopt);
}
- const auto iter_end = type_spec->types + type_spec->type_count;
- for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- const incfs::verified_map_ptr<ResTable_type>& type = *iter;
+ for (const auto& type_entry : type_spec->type_entries) {
+ const incfs::verified_map_ptr<ResTable_type>& type = type_entry.type;
size_t entry_count = dtohl(type->entryCount);
for (size_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
@@ -492,7 +463,7 @@
// A map of TypeSpec builders, each associated with an type index.
// We use these to accumulate the set of Types available for a TypeSpec, and later build a single,
// contiguous block of memory that holds all the Types together with the TypeSpec.
- std::unordered_map<int, std::unique_ptr<TypeSpecPtrBuilder>> type_builder_map;
+ std::unordered_map<int, std::unique_ptr<TypeSpecBuilder>> type_builder_map;
ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
while (iter.HasNext()) {
@@ -562,9 +533,9 @@
return {};
}
- std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1];
+ std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type_spec->id];
if (builder_ptr == nullptr) {
- builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec.verified());
+ builder_ptr = util::make_unique<TypeSpecBuilder>(type_spec.verified());
loaded_package->resource_ids_.set(type_spec->id, entry_count);
} else {
LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
@@ -584,7 +555,7 @@
}
// Type chunks must be preceded by their TypeSpec chunks.
- std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type->id - 1];
+ std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type->id];
if (builder_ptr != nullptr) {
builder_ptr->AddType(type.verified());
} else {
@@ -722,14 +693,9 @@
// Flatten and construct the TypeSpecs.
for (auto& entry : type_builder_map) {
- uint8_t type_idx = static_cast<uint8_t>(entry.first);
- TypeSpecPtr type_spec_ptr = entry.second->Build();
- if (type_spec_ptr == nullptr) {
- LOG(ERROR) << "Too many type configurations, overflow detected.";
- return {};
- }
-
- loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr);
+ TypeSpec type_spec = entry.second->Build();
+ uint8_t type_id = static_cast<uint8_t>(entry.first);
+ loaded_package->type_specs_[type_id] = std::move(type_spec);
}
return std::move(loaded_package);
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index a92694c..6fbd6aa 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -101,12 +101,7 @@
// Only pass invalidate_caches=false when it is known that the structure
// change in ApkAssets is due to a safe addition of resources with completely
// new resource IDs.
- //
- // Only pass in filter_incompatible_configs=false when you want to load all
- // configurations (including incompatible ones) such as when constructing an
- // idmap.
- bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true,
- bool filter_incompatible_configs = true);
+ bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true);
inline const std::vector<const ApkAssets*> GetApkAssets() const {
return apk_assets_;
@@ -298,6 +293,12 @@
// data failed.
base::expected<const ResolvedBag*, NullOrIOError> ResolveBag(SelectedValue& value) const;
+ // Returns the android::ResTable_typeSpec flags of the resource ID.
+ //
+ // Returns a null error if the resource could not be resolved, or an I/O error if reading
+ // resource data failed.
+ base::expected<uint32_t, NullOrIOError> GetResourceTypeSpecFlags(uint32_t resid) const;
+
const std::vector<uint32_t> GetBagResIdStack(uint32_t resid) const;
// Resets the resource resolution structures in preparation for the next resource retrieval.
@@ -330,15 +331,10 @@
private:
DISALLOW_COPY_AND_ASSIGN(AssetManager2);
- struct TypeConfig {
- incfs::verified_map_ptr<ResTable_type> type;
- ResTable_config config;
- };
-
// A collection of configurations and their associated ResTable_type that match the current
// AssetManager configuration.
struct FilteredConfigGroup {
- std::vector<TypeConfig> type_configs;
+ std::vector<const TypeSpec::TypeEntry*> type_entries;
};
// Represents an single package.
@@ -413,7 +409,7 @@
// Triggers the re-construction of lists of types that match the set configuration.
// This should always be called when mutating the AssetManager's configuration or ApkAssets set.
- void RebuildFilterList(bool filter_incompatible_configs = true);
+ void RebuildFilterList();
// Retrieves the APK paths of overlays that overlay non-system packages.
std::set<std::string> GetNonSystemOverlayPaths() const;
@@ -460,13 +456,9 @@
enum class Type {
INITIAL,
BETTER_MATCH,
- BETTER_MATCH_LOADER,
OVERLAID,
- OVERLAID_LOADER,
SKIPPED,
- SKIPPED_LOADER,
NO_ENTRY,
- NO_ENTRY_LOADER,
};
// Marks what kind of override this step was.
@@ -477,6 +469,9 @@
// Marks the package name of the better resource found in this step.
const std::string* package_name;
+
+ //
+ ApkAssetsCookie cookie = kInvalidCookie;
};
// Last resolved resource ID.
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index 17d97a2..891fb90 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -47,18 +47,19 @@
// TypeSpec is going to be immediately proceeded by
// an array of Type structs, all in the same block of memory.
struct TypeSpec {
- // Pointer to the mmapped data where flags are kept.
- // Flags denote whether the resource entry is public
- // and under which configurations it varies.
+ struct TypeEntry {
+ incfs::verified_map_ptr<ResTable_type> type;
+
+ // Type configurations are accessed frequently when setting up an AssetManager and querying
+ // resources. Access this cached configuration to minimize page faults.
+ ResTable_config config;
+ };
+
+ // Pointer to the mmapped data where flags are kept. Flags denote whether the resource entry is
+ // public and under which configurations it varies.
incfs::verified_map_ptr<ResTable_typeSpec> type_spec;
- // The number of types that follow this struct.
- // There is a type for each configuration that entries are defined for.
- size_t type_count;
-
- // Trick to easily access a variable number of Type structs
- // proceeding this struct, and to ensure their alignment.
- incfs::verified_map_ptr<ResTable_type> types[0];
+ std::vector<TypeEntry> type_entries;
base::expected<uint32_t, NullOrIOError> GetFlagsForEntryIndex(uint16_t entry_index) const {
if (entry_index >= dtohl(type_spec->entryCount)) {
@@ -92,11 +93,6 @@
PROPERTY_OVERLAY = 1U << 3U,
};
-// TypeSpecPtr points to a block of memory that holds a TypeSpec struct, followed by an array of
-// ResTable_type pointers.
-// TypeSpecPtr is a managed pointer that knows how to delete itself.
-using TypeSpecPtr = util::unique_cptr<TypeSpec>;
-
struct OverlayableInfo {
std::string name;
std::string actor;
@@ -239,17 +235,17 @@
inline const TypeSpec* GetTypeSpecByTypeIndex(uint8_t type_index) const {
// If the type IDs are offset in this package, we need to take that into account when searching
// for a type.
- return type_specs_[type_index - type_id_offset_].get();
+ const auto& type_spec = type_specs_.find(type_index + 1 - type_id_offset_);
+ if (type_spec == type_specs_.end()) {
+ return nullptr;
+ }
+ return &type_spec->second;
}
template <typename Func>
void ForEachTypeSpec(Func f) const {
- for (size_t i = 0; i < type_specs_.size(); i++) {
- const TypeSpecPtr& ptr = type_specs_[i];
- if (ptr != nullptr) {
- uint8_t type_id = ptr->type_spec->id;
- f(ptr.get(), type_id - 1);
- }
+ for (const auto& type_spec : type_specs_) {
+ f(type_spec.second, type_spec.first);
}
}
@@ -289,7 +285,7 @@
int type_id_offset_ = 0;
package_property_t property_flags_ = 0U;
- ByteBucketArray<TypeSpecPtr> type_specs_;
+ std::unordered_map<uint8_t, TypeSpec> type_specs_;
ByteBucketArray<uint32_t> resource_ids_;
std::vector<DynamicPackageEntry> dynamic_package_map_;
std::vector<const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>> overlayable_infos_;
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 471b0ee..e1c0fab7 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -55,6 +55,12 @@
basic_de_fr_assets_ = ApkAssets::Load("basic/basic_de_fr.apk");
ASSERT_NE(nullptr, basic_de_fr_assets_);
+ basic_xhdpi_assets_ = ApkAssets::Load("basic/basic_xhdpi-v4.apk");
+ ASSERT_NE(nullptr, basic_de_fr_assets_);
+
+ basic_xxhdpi_assets_ = ApkAssets::Load("basic/basic_xxhdpi-v4.apk");
+ ASSERT_NE(nullptr, basic_de_fr_assets_);
+
style_assets_ = ApkAssets::Load("styles/styles.apk");
ASSERT_NE(nullptr, style_assets_);
@@ -87,6 +93,8 @@
protected:
std::unique_ptr<const ApkAssets> basic_assets_;
std::unique_ptr<const ApkAssets> basic_de_fr_assets_;
+ std::unique_ptr<const ApkAssets> basic_xhdpi_assets_;
+ std::unique_ptr<const ApkAssets> basic_xxhdpi_assets_;
std::unique_ptr<const ApkAssets> style_assets_;
std::unique_ptr<const ApkAssets> lib_one_assets_;
std::unique_ptr<const ApkAssets> lib_two_assets_;
@@ -225,6 +233,24 @@
ASSERT_EQ("com.android.lib_one:string/foo", ToFormattedResourceString(*name));
}
+TEST_F(AssetManager2Test, GetResourceNameNonMatchingConfig) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({basic_de_fr_assets_.get()});
+
+ auto value = assetmanager.GetResourceName(basic::R::string::test1);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ("com.android.basic:string/test1", ToFormattedResourceString(*value));
+}
+
+TEST_F(AssetManager2Test, GetResourceTypeSpecFlags) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({basic_de_fr_assets_.get()});
+
+ auto value = assetmanager.GetResourceTypeSpecFlags(basic::R::string::test1);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(ResTable_typeSpec::SPEC_PUBLIC | ResTable_config::CONFIG_LOCALE, *value);
+}
+
TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({basic_assets_.get()});
@@ -442,6 +468,29 @@
EXPECT_EQ(*low_ref, value->resid);
}
+TEST_F(AssetManager2Test, DensityOverride) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({basic_assets_.get(), basic_xhdpi_assets_.get(),
+ basic_xxhdpi_assets_.get()});
+ assetmanager.SetConfiguration({
+ .density = ResTable_config::DENSITY_XHIGH,
+ .sdkVersion = 21,
+ });
+
+ auto value = assetmanager.GetResource(basic::R::string::density, false /*may_be_bag*/);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(Res_value::TYPE_STRING, value->type);
+ EXPECT_EQ("xhdpi", GetStringFromPool(assetmanager.GetStringPoolForCookie(value->cookie),
+ value->data));
+
+ value = assetmanager.GetResource(basic::R::string::density, false /*may_be_bag*/,
+ ResTable_config::DENSITY_XXHIGH);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(Res_value::TYPE_STRING, value->type);
+ EXPECT_EQ("xxhdpi", GetStringFromPool(assetmanager.GetStringPoolForCookie(value->cookie),
+ value->data));
+}
+
TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({basic_assets_.get()});
@@ -716,7 +765,7 @@
auto result = assetmanager.GetLastResourceResolution();
EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n"
- "\tFor config -de\n\tFound initial: com.android.basic", result);
+ "\tFor config -de\n\tFound initial: com.android.basic (basic/basic.apk)", result);
}
TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) {
@@ -736,8 +785,8 @@
auto result = assetmanager.GetLastResourceResolution();
EXPECT_EQ("Resolution for 0x7f030000 com.android.basic:string/test1\n"
"\tFor config -de\n"
- "\tFound initial: com.android.basic\n"
- "\tFound better: com.android.basic -de", result);
+ "\tFound initial: com.android.basic (basic/basic.apk)\n"
+ "\tFound better: com.android.basic (basic/basic_de_fr.apk) -de", result);
}
TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) {
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 6357411..9aa3634 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -65,10 +65,10 @@
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
+ ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
- auto type = type_spec->types[0];
- ASSERT_TRUE(LoadedPackage::GetEntry(type, entry_index).has_value());
+ auto type = type_spec->type_entries[0];
+ ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value());
}
TEST(LoadedArscTest, LoadSparseEntryApp) {
@@ -89,10 +89,10 @@
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
+ ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
- auto type = type_spec->types[0];
- ASSERT_TRUE(LoadedPackage::GetEntry(type, entry_index).has_value());
+ auto type = type_spec->type_entries[0];
+ ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value());
}
TEST(LoadedArscTest, LoadSharedLibrary) {
@@ -176,13 +176,13 @@
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
+ ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
auto type_name16 = package->GetTypeStringPool()->stringAt(type_spec->type_spec->id - 1);
ASSERT_TRUE(type_name16.has_value());
EXPECT_THAT(util::Utf16ToUtf8(*type_name16), StrEq("string"));
- ASSERT_TRUE(LoadedPackage::GetEntry(type_spec->types[0], entry_index).has_value());
+ ASSERT_TRUE(LoadedPackage::GetEntry(type_spec->type_entries[0].type, entry_index).has_value());
}
// AAPT(2) generates resource tables with chunks in a certain order. The rule is that
@@ -217,11 +217,11 @@
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0);
ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
+ ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
type_spec = package->GetTypeSpecByTypeIndex(1);
ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
+ ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
}
TEST(LoadedArscTest, LoadOverlayable) {
@@ -363,10 +363,10 @@
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
ASSERT_THAT(type_spec, NotNull());
- ASSERT_THAT(type_spec->type_count, Ge(1u));
+ ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
- auto type = type_spec->types[0];
- ASSERT_TRUE(LoadedPackage::GetEntry(type, entry_index).has_value());
+ auto type = type_spec->type_entries[0];
+ ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value());
}
// structs with size fields (like Res_value, ResTable_entry) should be
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index dd24763..3aa5b4b 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -16,21 +16,134 @@
#pragma once
+#include "pipeline/skia/SkiaDisplayList.h"
+
+#include <memory>
+
namespace android {
namespace uirenderer {
namespace VectorDrawable {
class Tree;
};
-namespace skiapipeline {
-class SkiaDisplayList;
-}
typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
/**
* Data structure that holds the list of commands used in display list stream
*/
-using DisplayList = skiapipeline::SkiaDisplayList;
+//using DisplayList = skiapipeline::SkiaDisplayList;
+class DisplayList {
+public:
+ // Constructs an empty (invalid) DisplayList
+ explicit DisplayList() {}
+
+ // Constructs a DisplayList from a SkiaDisplayList
+ explicit DisplayList(std::unique_ptr<skiapipeline::SkiaDisplayList> impl)
+ : mImpl(std::move(impl)) {}
+
+ // Move support
+ DisplayList(DisplayList&& other) : mImpl(std::move(other.mImpl)) {}
+ DisplayList& operator=(DisplayList&& other) {
+ mImpl = std::move(other.mImpl);
+ return *this;
+ }
+
+ // No copy support
+ DisplayList(const DisplayList& other) = delete;
+ DisplayList& operator=(const DisplayList&) = delete;
+
+ void updateChildren(std::function<void(RenderNode*)> updateFn) {
+ mImpl->updateChildren(std::move(updateFn));
+ }
+
+ [[nodiscard]] explicit operator bool() const {
+ return mImpl.get() != nullptr;
+ }
+
+ // If true this DisplayList contains a backing content, even if that content is empty
+ // If false, there this DisplayList is in an "empty" state
+ [[nodiscard]] bool isValid() const {
+ return mImpl.get() != nullptr;
+ }
+
+ [[nodiscard]] bool isEmpty() const {
+ return !hasContent();
+ }
+
+ [[nodiscard]] bool hasContent() const {
+ return mImpl && !(mImpl->isEmpty());
+ }
+
+ [[nodiscard]] bool containsProjectionReceiver() const {
+ return mImpl && mImpl->containsProjectionReceiver();
+ }
+
+ [[nodiscard]] skiapipeline::SkiaDisplayList* asSkiaDl() {
+ return mImpl.get();
+ }
+
+ [[nodiscard]] const skiapipeline::SkiaDisplayList* asSkiaDl() const {
+ return mImpl.get();
+ }
+
+ [[nodiscard]] bool hasVectorDrawables() const {
+ return mImpl && mImpl->hasVectorDrawables();
+ }
+
+ void clear(RenderNode* owningNode = nullptr) {
+ if (mImpl && owningNode && mImpl->reuseDisplayList(owningNode)) {
+ // TODO: This is a bit sketchy to have a unique_ptr temporarily owned twice
+ // Do something to cleanup reuseDisplayList passing itself to the RenderNode
+ mImpl.release();
+ } else {
+ mImpl = nullptr;
+ }
+ }
+
+ [[nodiscard]] size_t getUsedSize() const {
+ return mImpl ? mImpl->getUsedSize() : 0;
+ }
+
+ [[nodiscard]] size_t getAllocatedSize() const {
+ return mImpl ? mImpl->getAllocatedSize() : 0;
+ }
+
+ void output(std::ostream& output, uint32_t level) const {
+ if (mImpl) {
+ mImpl->output(output, level);
+ }
+ }
+
+ [[nodiscard]] bool hasFunctor() const {
+ return mImpl && mImpl->hasFunctor();
+ }
+
+ bool prepareListAndChildren(
+ TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
+ std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
+ return mImpl && mImpl->prepareListAndChildren(
+ observer, info, functorsNeedLayer, std::move(childFn));
+ }
+
+ void syncContents(const WebViewSyncData& data) {
+ if (mImpl) {
+ mImpl->syncContents(data);
+ }
+ }
+
+ [[nodiscard]] bool hasText() const {
+ return mImpl && mImpl->hasText();
+ }
+
+ void applyColorTransform(ColorTransform transform) {
+ if (mImpl) {
+ mImpl->mDisplayList.applyColorTransform(transform);
+ }
+ }
+
+private:
+ std::unique_ptr<skiapipeline::SkiaDisplayList> mImpl;
+};
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index ba44d05..65f4e8c 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -15,7 +15,9 @@
*/
#include "Properties.h"
+
#include "Debug.h"
+#include "log/log_main.h"
#ifdef __ANDROID__
#include "HWUIProperties.sysprop.h"
#endif
@@ -190,15 +192,12 @@
return sRenderPipelineType;
}
-void Properties::overrideRenderPipelineType(RenderPipelineType type) {
+void Properties::overrideRenderPipelineType(RenderPipelineType type, bool inUnitTest) {
// If we're doing actual rendering then we can't change the renderer after it's been set.
- // Unit tests can freely change this as often as it wants, though, as there's no actual
- // GL rendering happening
- if (sRenderPipelineType != RenderPipelineType::NotInitialized) {
- LOG_ALWAYS_FATAL_IF(sRenderPipelineType != type,
- "Trying to change pipeline but it's already set");
- return;
- }
+ // Unit tests can freely change this as often as it wants.
+ LOG_ALWAYS_FATAL_IF(sRenderPipelineType != RenderPipelineType::NotInitialized &&
+ sRenderPipelineType != type && !inUnitTest,
+ "Trying to change pipeline but it's already set.");
sRenderPipelineType = type;
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 85a0f4a..1639143 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -238,7 +238,7 @@
static bool enableRTAnimations;
// Used for testing only to change the render pipeline.
- static void overrideRenderPipelineType(RenderPipelineType);
+ static void overrideRenderPipelineType(RenderPipelineType, bool inUnitTest = false);
static bool runningInEmulator;
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 89e3df7..a6a7b12 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -18,7 +18,6 @@
#include "CanvasTransform.h"
#include "hwui/Bitmap.h"
-#include "hwui/Canvas.h"
#include "utils/Macros.h"
#include "utils/TypeLogic.h"
@@ -29,7 +28,6 @@
#include "SkPaint.h"
#include "SkPath.h"
#include "SkRect.h"
-#include "SkTemplates.h"
#include <vector>
@@ -40,6 +38,11 @@
class FunctorDrawable;
}
+namespace VectorDrawable {
+class Tree;
+}
+typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
+
enum class DisplayListOpType : uint8_t {
#define X(T) T,
#include "DisplayListOps.in"
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 74c70c8..44f54ee 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -70,15 +70,17 @@
RenderNode::~RenderNode() {
ImmediateRemoved observer(nullptr);
deleteDisplayList(observer);
- delete mStagingDisplayList;
LOG_ALWAYS_FATAL_IF(hasLayer(), "layer missed detachment!");
}
-void RenderNode::setStagingDisplayList(DisplayList* displayList) {
- mValid = (displayList != nullptr);
+void RenderNode::setStagingDisplayList(DisplayList&& newData) {
+ mValid = newData.isValid();
mNeedsDisplayListSync = true;
- delete mStagingDisplayList;
- mStagingDisplayList = displayList;
+ mStagingDisplayList = std::move(newData);
+}
+
+void RenderNode::discardStagingDisplayList() {
+ setStagingDisplayList(DisplayList());
}
/**
@@ -101,32 +103,22 @@
properties().debugOutputProperties(output, level + 1);
- if (mDisplayList) {
- mDisplayList->output(output, level);
- }
+ mDisplayList.output(output, level);
output << std::string(level * 2, ' ') << "/RenderNode(" << getName() << " " << this << ")";
output << std::endl;
}
int RenderNode::getUsageSize() {
int size = sizeof(RenderNode);
- if (mStagingDisplayList) {
- size += mStagingDisplayList->getUsedSize();
- }
- if (mDisplayList && mDisplayList != mStagingDisplayList) {
- size += mDisplayList->getUsedSize();
- }
+ size += mStagingDisplayList.getUsedSize();
+ size += mDisplayList.getUsedSize();
return size;
}
int RenderNode::getAllocatedSize() {
int size = sizeof(RenderNode);
- if (mStagingDisplayList) {
- size += mStagingDisplayList->getAllocatedSize();
- }
- if (mDisplayList && mDisplayList != mStagingDisplayList) {
- size += mDisplayList->getAllocatedSize();
- }
+ size += mStagingDisplayList.getAllocatedSize();
+ size += mDisplayList.getAllocatedSize();
return size;
}
@@ -242,9 +234,9 @@
bool willHaveFunctor = false;
if (info.mode == TreeInfo::MODE_FULL && mStagingDisplayList) {
- willHaveFunctor = mStagingDisplayList->hasFunctor();
+ willHaveFunctor = mStagingDisplayList.hasFunctor();
} else if (mDisplayList) {
- willHaveFunctor = mDisplayList->hasFunctor();
+ willHaveFunctor = mDisplayList.hasFunctor();
}
bool childFunctorsNeedLayer =
mProperties.prepareForFunctorPresence(willHaveFunctor, functorsNeedLayer);
@@ -259,8 +251,8 @@
}
if (mDisplayList) {
- info.out.hasFunctors |= mDisplayList->hasFunctor();
- bool isDirty = mDisplayList->prepareListAndChildren(
+ info.out.hasFunctors |= mDisplayList.hasFunctor();
+ bool isDirty = mDisplayList.prepareListAndChildren(
observer, info, childFunctorsNeedLayer,
[](RenderNode* child, TreeObserver& observer, TreeInfo& info,
bool functorsNeedLayer) {
@@ -314,16 +306,15 @@
// Make sure we inc first so that we don't fluctuate between 0 and 1,
// which would thrash the layer cache
if (mStagingDisplayList) {
- mStagingDisplayList->updateChildren([](RenderNode* child) { child->incParentRefCount(); });
+ mStagingDisplayList.updateChildren([](RenderNode* child) { child->incParentRefCount(); });
}
deleteDisplayList(observer, info);
- mDisplayList = mStagingDisplayList;
- mStagingDisplayList = nullptr;
+ mDisplayList = std::move(mStagingDisplayList);
if (mDisplayList) {
WebViewSyncData syncData {
.applyForceDark = info && !info->disableForceDark
};
- mDisplayList->syncContents(syncData);
+ mDisplayList.syncContents(syncData);
handleForceDark(info);
}
}
@@ -333,15 +324,18 @@
return;
}
auto usage = usageHint();
- const auto& children = mDisplayList->mChildNodes;
- if (mDisplayList->hasText()) {
+ FatVector<RenderNode*, 6> children;
+ mDisplayList.updateChildren([&children](RenderNode* node) {
+ children.push_back(node);
+ });
+ if (mDisplayList.hasText()) {
usage = UsageHint::Foreground;
}
if (usage == UsageHint::Unknown) {
if (children.size() > 1) {
usage = UsageHint::Background;
} else if (children.size() == 1 &&
- children.front().getRenderNode()->usageHint() !=
+ children.front()->usageHint() !=
UsageHint::Background) {
usage = UsageHint::Background;
}
@@ -350,7 +344,7 @@
// Crude overlap check
SkRect drawn = SkRect::MakeEmpty();
for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
- const auto& child = iter->getRenderNode();
+ const auto& child = *iter;
// We use stagingProperties here because we haven't yet sync'd the children
SkRect bounds = SkRect::MakeXYWH(child->stagingProperties().getX(), child->stagingProperties().getY(),
child->stagingProperties().getWidth(), child->stagingProperties().getHeight());
@@ -361,7 +355,7 @@
drawn.join(bounds);
}
}
- mDisplayList->mDisplayList.applyColorTransform(
+ mDisplayList.applyColorTransform(
usage == UsageHint::Background ? ColorTransform::Dark : ColorTransform::Light);
}
@@ -378,20 +372,17 @@
void RenderNode::deleteDisplayList(TreeObserver& observer, TreeInfo* info) {
if (mDisplayList) {
- mDisplayList->updateChildren(
+ mDisplayList.updateChildren(
[&observer, info](RenderNode* child) { child->decParentRefCount(observer, info); });
- if (!mDisplayList->reuseDisplayList(this)) {
- delete mDisplayList;
- }
+ mDisplayList.clear(this);
}
- mDisplayList = nullptr;
}
void RenderNode::destroyHardwareResources(TreeInfo* info) {
if (hasLayer()) {
this->setLayerSurface(nullptr);
}
- setStagingDisplayList(nullptr);
+ discardStagingDisplayList();
ImmediateRemoved observer(info);
deleteDisplayList(observer, info);
@@ -402,7 +393,7 @@
this->setLayerSurface(nullptr);
}
if (mDisplayList) {
- mDisplayList->updateChildren([](RenderNode* child) { child->destroyLayers(); });
+ mDisplayList.updateChildren([](RenderNode* child) { child->destroyLayers(); });
}
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 6d5e62e..39ea53b 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -100,16 +100,17 @@
// See flags defined in DisplayList.java
enum ReplayFlag { kReplayFlag_ClipChildren = 0x1 };
- void setStagingDisplayList(DisplayList* newData);
+ void setStagingDisplayList(DisplayList&& newData);
+ void discardStagingDisplayList();
void output();
int getUsageSize();
int getAllocatedSize();
- bool isRenderable() const { return mDisplayList && !mDisplayList->isEmpty(); }
+ bool isRenderable() const { return mDisplayList.hasContent(); }
bool hasProjectionReceiver() const {
- return mDisplayList && mDisplayList->containsProjectionReceiver();
+ return mDisplayList.containsProjectionReceiver();
}
const char* getName() const { return mName.string(); }
@@ -168,12 +169,14 @@
bool nothingToDraw() const {
const Outline& outline = properties().getOutline();
- return mDisplayList == nullptr || properties().getAlpha() <= 0 ||
+ return !mDisplayList.isValid() || properties().getAlpha() <= 0 ||
(outline.getShouldClip() && outline.isEmpty()) || properties().getScaleX() == 0 ||
properties().getScaleY() == 0;
}
- const DisplayList* getDisplayList() const { return mDisplayList; }
+ const DisplayList& getDisplayList() const { return mDisplayList; }
+ // TODO: can this be cleaned up?
+ DisplayList& getDisplayList() { return mDisplayList; }
// Note: The position callbacks are relying on the listener using
// the frameNumber to appropriately batch/synchronize these transactions.
@@ -252,8 +255,8 @@
bool mNeedsDisplayListSync;
// WARNING: Do not delete this directly, you must go through deleteDisplayList()!
- DisplayList* mDisplayList;
- DisplayList* mStagingDisplayList;
+ DisplayList mDisplayList;
+ DisplayList mStagingDisplayList;
int64_t mDamageGenerationId;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 815ffde..1ebc489 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -819,10 +819,10 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) {
+ const SkRuntimeShaderBuilder& effectBuilder) {
sk_sp<uirenderer::skiapipeline::AnimatedRipple> drawable(
new uirenderer::skiapipeline::AnimatedRipple(x, y, radius, paint, progress,
- runtimeEffect));
+ effectBuilder));
mCanvas->drawDrawable(drawable.get());
}
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index fa7d373..82b7de4 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -53,9 +53,9 @@
LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas");
}
- virtual uirenderer::DisplayList* finishRecording() override {
+ virtual uirenderer::DisplayList finishRecording() override {
LOG_ALWAYS_FATAL("SkiaCanvas does not produce a DisplayList");
- return nullptr;
+ return uirenderer::DisplayList();
}
virtual void enableZ(bool enableZ) override {
LOG_ALWAYS_FATAL("SkiaCanvas does not support enableZ");
@@ -152,7 +152,7 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) override;
+ const SkRuntimeShaderBuilder& effectBuilder) override;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h
index 737d605..17b936a 100644
--- a/libs/hwui/WebViewFunctorManager.h
+++ b/libs/hwui/WebViewFunctorManager.h
@@ -19,11 +19,11 @@
#include <private/hwui/WebViewFunctor.h>
#ifdef __ANDROID__ // Layoutlib does not support render thread
#include <renderthread/RenderProxy.h>
-#else
-#include <utils/Log.h>
#endif
#include <utils/LightRefBase.h>
+#include <utils/Log.h>
+#include <utils/StrongPointer.h>
#include <mutex>
#include <vector>
diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h
index ea9fea97..fa0c45b 100644
--- a/libs/hwui/canvas/CanvasOps.h
+++ b/libs/hwui/canvas/CanvasOps.h
@@ -161,7 +161,7 @@
}
SkRuntimeShaderBuilder::BuilderUniform radiusU =
- runtimeEffectBuilder.uniform("in_maxRadius");
+ runtimeEffectBuilder.uniform("in_radius");
if (radiusU.fVar != nullptr) {
radiusU = radius->value;
}
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index d0c996b..184b11e 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -31,7 +31,7 @@
class SkAnimatedImage;
class SkCanvasState;
-class SkRuntimeEffect;
+class SkRuntimeShaderBuilder;
class SkVertices;
namespace minikin {
@@ -118,7 +118,7 @@
virtual void resetRecording(int width, int height,
uirenderer::RenderNode* renderNode = nullptr) = 0;
- virtual uirenderer::DisplayList* finishRecording() = 0;
+ [[nodiscard]] virtual uirenderer::DisplayList finishRecording() = 0;
virtual void enableZ(bool enableZ) = 0;
bool isHighContrastText() const { return uirenderer::Properties::enableHighContrastText; }
@@ -139,7 +139,7 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) = 0;
+ const SkRuntimeShaderBuilder& effectBuilder) = 0;
virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) = 0;
virtual void drawRenderNode(uirenderer::RenderNode* renderNode) = 0;
diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp
index b3f7627..764bc4c 100644
--- a/libs/hwui/hwui/ImageDecoder.cpp
+++ b/libs/hwui/hwui/ImageDecoder.cpp
@@ -52,6 +52,7 @@
, mOutColorType(mCodec->computeOutputColorType(kN32_SkColorType))
, mUnpremultipliedRequired(false)
, mOutColorSpace(getDefaultColorSpace())
+ , mHandleRestorePrevious(true)
{
mTargetSize = swapWidthHeight() ? SkISize { mDecodeSize.height(), mDecodeSize.width() }
: mDecodeSize;
@@ -230,6 +231,13 @@
return true;
}
+void ImageDecoder::setHandleRestorePrevious(bool handle) {
+ mHandleRestorePrevious = handle;
+ if (!handle) {
+ mRestoreFrame = nullptr;
+ }
+}
+
bool ImageDecoder::advanceFrame() {
const int frameIndex = ++mOptions.fFrameIndex;
const int frameCount = mCodec->codec()->getFrameCount();
@@ -255,6 +263,7 @@
case RestoreState::kDoNothing:
case RestoreState::kNeedsRestore:
mRestoreState = RestoreState::kFirstRPFrame;
+ mOptions.fPriorFrame = frameIndex - 1;
break;
case RestoreState::kFirstRPFrame:
mRestoreState = RestoreState::kRPFrame;
@@ -315,29 +324,19 @@
return mOptions.fFrameIndex >= mCodec->codec()->getFrameCount();
}
-SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) {
- // This was checked inside setTargetSize, but it's possible the first frame
- // was opaque, so that method succeeded, but after calling advanceFrame, the
- // current frame is not opaque.
- if (mUnpremultipliedRequired && !opaque()) {
- // Allow using a matrix to handle orientation, but not scaling.
- if (requires_matrix_scaling(swapWidthHeight(), mDecodeSize, mTargetSize)) {
- return SkCodec::kInvalidScale;
- }
+bool ImageDecoder::handleRestorePrevious(const SkImageInfo& outputInfo, void* pixels,
+ size_t rowBytes) {
+ if (!mHandleRestorePrevious) {
+ return true;
}
- void* decodePixels = pixels;
- size_t decodeRowBytes = rowBytes;
- const auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, getOutAlphaType(),
- getOutputColorSpace());
- const auto outputInfo = getOutputInfo();
switch (mRestoreState) {
case RestoreState::kFirstRPFrame:{
// This frame is marked kRestorePrevious. The prior frame should be in
// |pixels|, and it is what we'll restore after each consecutive
// kRestorePrevious frame. Cache it now.
if (!(mRestoreFrame = Bitmap::allocateHeapBitmap(outputInfo))) {
- return SkCodec::kInternalError;
+ return false;
}
const uint8_t* srcRow = static_cast<uint8_t*>(pixels);
@@ -366,7 +365,29 @@
case RestoreState::kDoNothing:
break;
}
+ return true;
+}
+SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) {
+ // This was checked inside setTargetSize, but it's possible the first frame
+ // was opaque, so that method succeeded, but after calling advanceFrame, the
+ // current frame is not opaque.
+ if (mUnpremultipliedRequired && !opaque()) {
+ // Allow using a matrix to handle orientation, but not scaling.
+ if (requires_matrix_scaling(swapWidthHeight(), mDecodeSize, mTargetSize)) {
+ return SkCodec::kInvalidScale;
+ }
+ }
+
+ const auto outputInfo = getOutputInfo();
+ if (!handleRestorePrevious(outputInfo, pixels, rowBytes)) {
+ return SkCodec::kInternalError;
+ }
+
+ void* decodePixels = pixels;
+ size_t decodeRowBytes = rowBytes;
+ const auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, getOutAlphaType(),
+ getOutputColorSpace());
// Used if we need a temporary before scaling or subsetting.
// FIXME: Use scanline decoding on only a couple lines to save memory. b/70709380.
SkBitmap tmp;
diff --git a/libs/hwui/hwui/ImageDecoder.h b/libs/hwui/hwui/ImageDecoder.h
index 90261b1..1b309bc 100644
--- a/libs/hwui/hwui/ImageDecoder.h
+++ b/libs/hwui/hwui/ImageDecoder.h
@@ -73,6 +73,9 @@
SkCodec::FrameInfo getCurrentFrameInfo();
+ // Set whether the ImageDecoder should handle RestorePrevious frames.
+ void setHandleRestorePrevious(bool handle);
+
private:
// State machine for keeping track of how to handle RestorePrevious (RP)
// frames in decode().
@@ -105,6 +108,7 @@
SkAndroidCodec::AndroidOptions mOptions;
bool mCurrentFrameIsIndependent;
bool mCurrentFrameIsOpaque;
+ bool mHandleRestorePrevious;
RestoreState mRestoreState;
sk_sp<Bitmap> mRestoreFrame;
std::optional<SkIRect> mCropRect;
@@ -115,6 +119,8 @@
SkAlphaType getOutAlphaType() const;
sk_sp<SkColorSpace> getOutputColorSpace() const;
bool swapWidthHeight() const;
+ // Store/restore a frame if necessary. Returns false on error.
+ bool handleRestorePrevious(const SkImageInfo&, void* pixels, size_t rowBytes);
};
} // namespace android
diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp
index eb9885a..05278f2 100755
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -3,11 +3,12 @@
#include "Bitmap.h"
#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkColor.h"
+#include "SkColorSpace.h"
#include "SkPixelRef.h"
#include "SkImageEncoder.h"
#include "SkImageInfo.h"
-#include "SkColor.h"
-#include "SkColorSpace.h"
#include "GraphicsJNI.h"
#include "SkStream.h"
#include "SkWebpEncoder.h"
diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp
index 52522a3..cf02051 100644
--- a/libs/hwui/jni/BitmapFactory.cpp
+++ b/libs/hwui/jni/BitmapFactory.cpp
@@ -8,9 +8,11 @@
#include "MimeType.h"
#include "NinePatchPeeker.h"
#include "SkAndroidCodec.h"
+#include "SkCanvas.h"
#include "SkMath.h"
#include "SkPixelRef.h"
#include "SkStream.h"
+#include "SkString.h"
#include "SkUtils.h"
#include "Utils.h"
diff --git a/libs/hwui/jni/GraphicsJNI.h b/libs/hwui/jni/GraphicsJNI.h
index 541d5a5..ba407f2 100644
--- a/libs/hwui/jni/GraphicsJNI.h
+++ b/libs/hwui/jni/GraphicsJNI.h
@@ -24,6 +24,7 @@
namespace skia {
class BitmapRegionDecoder;
}
+class Canvas;
class Paint;
struct Typeface;
}
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index aaec60b..ad3fd55 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -1,3 +1,6 @@
+#undef LOG_TAG
+#define LOG_TAG "ShaderJNI"
+
#include "GraphicsJNI.h"
#include "SkColorFilter.h"
#include "SkGradientShader.h"
@@ -232,53 +235,72 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr,
- jbyteArray inputs, jlongArray inputShaders, jlong colorSpaceHandle, jboolean isOpaque) {
- SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(shaderFactory);
- AutoJavaByteArray arInputs(env, inputs);
-
- std::vector<sk_sp<SkShader>> shaderVector;
- if (inputShaders) {
- jsize shaderCount = env->GetArrayLength(inputShaders);
- shaderVector.resize(shaderCount);
- jlong* arrayPtr = env->GetLongArrayElements(inputShaders, NULL);
- for (int i = 0; i < shaderCount; i++) {
- shaderVector[i] = sk_ref_sp(reinterpret_cast<SkShader*>(arrayPtr[i]));
- }
- env->ReleaseLongArrayElements(inputShaders, arrayPtr, 0);
- }
-
- sk_sp<SkData> fData;
- fData = SkData::MakeWithCopy(arInputs.ptr(), arInputs.length());
- const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
- sk_sp<SkShader> shader = effect->makeShader(fData, shaderVector.data(), shaderVector.size(),
- matrix, isOpaque == JNI_TRUE);
- ThrowIAE_IfNull(env, shader);
-
- return reinterpret_cast<jlong>(shader.release());
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong RuntimeShader_createShaderFactory(JNIEnv* env, jobject, jstring sksl) {
+static jlong RuntimeShader_createShaderBuilder(JNIEnv* env, jobject, jstring sksl) {
ScopedUtfChars strSksl(env, sksl);
auto result = SkRuntimeEffect::Make(SkString(strSksl.c_str()));
sk_sp<SkRuntimeEffect> effect = std::get<0>(result);
- if (!effect) {
+ if (effect.get() == nullptr) {
const auto& err = std::get<1>(result);
doThrowIAE(env, err.c_str());
+ return 0;
}
- return reinterpret_cast<jlong>(effect.release());
+ return reinterpret_cast<jlong>(new SkRuntimeShaderBuilder(std::move(effect)));
}
-///////////////////////////////////////////////////////////////////////////////////////////////
-
-static void Effect_safeUnref(SkRuntimeEffect* effect) {
- SkSafeUnref(effect);
+static void SkRuntimeShaderBuilder_delete(SkRuntimeShaderBuilder* builder) {
+ delete builder;
}
static jlong RuntimeShader_getNativeFinalizer(JNIEnv*, jobject) {
- return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Effect_safeUnref));
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(&SkRuntimeShaderBuilder_delete));
+}
+
+static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderBuilder, jlong matrixPtr,
+ jboolean isOpaque) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
+ sk_sp<SkShader> shader = builder->makeShader(matrix, isOpaque == JNI_TRUE);
+ ThrowIAE_IfNull(env, shader);
+ return reinterpret_cast<jlong>(shader.release());
+}
+
+static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ return jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", fmt, args);
+ va_end(args);
+}
+
+static void RuntimeShader_updateUniforms(JNIEnv* env, jobject, jlong shaderBuilder,
+ jstring jUniformName, jfloatArray jvalues) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ ScopedUtfChars name(env, jUniformName);
+ AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess);
+
+ SkRuntimeShaderBuilder::BuilderUniform uniform = builder->uniform(name.c_str());
+ if (uniform.fVar == nullptr) {
+ ThrowIAEFmt(env, "unable to find uniform named %s", name.c_str());
+ } else if (!uniform.set<float>(autoValues.ptr(), autoValues.length())) {
+ ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]",
+ uniform.fVar->sizeInBytes(), sizeof(float) * autoValues.length());
+ }
+}
+
+static void RuntimeShader_updateShader(JNIEnv* env, jobject, jlong shaderBuilder,
+ jstring jUniformName, jlong shaderHandle) {
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder);
+ ScopedUtfChars name(env, jUniformName);
+ SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
+
+ SkRuntimeShaderBuilder::BuilderChild child = builder->child(name.c_str());
+ if (child.fIndex == -1) {
+ ThrowIAEFmt(env, "unable to find shader named %s", name.c_str());
+ return;
+ }
+
+ builder->child(name.c_str()) = sk_ref_sp(shader);
}
///////////////////////////////////////////////////////////////////////////////////////////////
@@ -313,10 +335,11 @@
};
static const JNINativeMethod gRuntimeShaderMethods[] = {
- { "nativeGetFinalizer", "()J", (void*)RuntimeShader_getNativeFinalizer },
- { "nativeCreate", "(JJ[B[JJZ)J", (void*)RuntimeShader_create },
- { "nativeCreateShaderFactory", "(Ljava/lang/String;)J",
- (void*)RuntimeShader_createShaderFactory },
+ {"nativeGetFinalizer", "()J", (void*)RuntimeShader_getNativeFinalizer},
+ {"nativeCreateShader", "(JJZ)J", (void*)RuntimeShader_create},
+ {"nativeCreateBuilder", "(Ljava/lang/String;)J", (void*)RuntimeShader_createShaderBuilder},
+ {"nativeUpdateUniforms", "(JLjava/lang/String;[F)V", (void*)RuntimeShader_updateUniforms},
+ {"nativeUpdateShader", "(JLjava/lang/String;J)V", (void*)RuntimeShader_updateShader},
};
int register_android_graphics_Shader(JNIEnv* env)
diff --git a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
index f4877f4..926e233 100644
--- a/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
+++ b/libs/hwui/jni/android_graphics_DisplayListCanvas.cpp
@@ -98,9 +98,11 @@
canvas->enableZ(reorderEnable);
}
-static jlong android_view_DisplayListCanvas_finishRecording(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr) {
+static void android_view_DisplayListCanvas_finishRecording(
+ CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong renderNodePtr) {
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
- return reinterpret_cast<jlong>(canvas->finishRecording());
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ renderNode->setStagingDisplayList(canvas->finishRecording());
}
static void android_view_DisplayListCanvas_drawRenderNode(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jlong renderNodePtr) {
@@ -142,7 +144,8 @@
static void android_view_DisplayListCanvas_drawRippleProps(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr,
jlong xPropPtr, jlong yPropPtr,
jlong radiusPropPtr, jlong paintPropPtr,
- jlong progressPropPtr, jlong effectPtr) {
+ jlong progressPropPtr,
+ jlong builderPtr) {
Canvas* canvas = reinterpret_cast<Canvas*>(canvasPtr);
CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
@@ -150,8 +153,8 @@
CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
CanvasPropertyPrimitive* progressProp =
reinterpret_cast<CanvasPropertyPrimitive*>(progressPropPtr);
- SkRuntimeEffect* effect = reinterpret_cast<SkRuntimeEffect*>(effectPtr);
- canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, sk_ref_sp(effect));
+ SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(builderPtr);
+ canvas->drawRipple(xProp, yProp, radiusProp, paintProp, progressProp, *builder);
}
static void android_view_DisplayListCanvas_drawWebViewFunctor(CRITICAL_JNI_PARAMS_COMMA jlong canvasPtr, jint functor) {
@@ -172,7 +175,7 @@
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureSize },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_DisplayListCanvas_getMaxTextureSize },
{ "nEnableZ", "(JZ)V", (void*) android_view_DisplayListCanvas_enableZ },
- { "nFinishRecording", "(J)J", (void*) android_view_DisplayListCanvas_finishRecording },
+ { "nFinishRecording", "(JJ)V", (void*) android_view_DisplayListCanvas_finishRecording },
{ "nDrawRenderNode", "(JJ)V", (void*) android_view_DisplayListCanvas_drawRenderNode },
{ "nDrawTextureLayer", "(JJ)V", (void*) android_view_DisplayListCanvas_drawTextureLayer },
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_DisplayListCanvas_drawCircleProps },
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index 6f4ba89..8b35d96 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -76,11 +76,9 @@
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&releaseRenderNode));
}
-static void android_view_RenderNode_setDisplayList(JNIEnv* env,
- jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
+static void android_view_RenderNode_discardDisplayList(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
- renderNode->setStagingDisplayList(newData);
+ renderNode->discardStagingDisplayList();
}
static jboolean android_view_RenderNode_isValid(CRITICAL_JNI_PARAMS_COMMA jlong renderNodePtr) {
@@ -657,18 +655,11 @@
{ "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator },
{ "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators },
{ "nRequestPositionUpdates", "(JLandroid/graphics/RenderNode$PositionUpdateListener;)V", (void*) android_view_RenderNode_requestPositionUpdates },
- { "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
-
-
-// ----------------------------------------------------------------------------
-// Fast JNI via @CriticalNative annotation in RenderNode.java
-// ----------------------------------------------------------------------------
- { "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
-
// ----------------------------------------------------------------------------
// Critical JNI via @CriticalNative annotation in RenderNode.java
// ----------------------------------------------------------------------------
+ { "nDiscardDisplayList", "(J)V", (void*) android_view_RenderNode_discardDisplayList },
{ "nIsValid", "(J)Z", (void*) android_view_RenderNode_isValid },
{ "nSetLayerType", "(JI)Z", (void*) android_view_RenderNode_setLayerType },
{ "nGetLayerType", "(J)I", (void*) android_view_RenderNode_getLayerType },
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index f612bce..943423f 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -33,6 +33,7 @@
#include <hwui/Paint.h>
#include <hwui/Typeface.h>
#include <minikin/FontFamily.h>
+#include <minikin/FontFileParser.h>
#include <ui/FatVector.h>
#include <memory>
@@ -233,6 +234,51 @@
///////////////////////////////////////////////////////////////////////////////
+// Fast Native
+static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) {
+ NPE_CHECK_RETURN_ZERO(env, buffer);
+ const void* fontPtr = env->GetDirectBufferAddress(buffer);
+ if (fontPtr == nullptr) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
+ return 0;
+ }
+ jlong fontSize = env->GetDirectBufferCapacity(buffer);
+ if (fontSize <= 0) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "buffer size must not be zero or negative");
+ return 0;
+ }
+ minikin::FontFileParser parser(fontPtr, fontSize, index);
+ std::optional<uint32_t> revision = parser.getFontRevision();
+ if (!revision.has_value()) {
+ return -1L;
+ }
+ return revision.value();
+}
+
+static jstring FontFileUtil_getFontPostScriptName(JNIEnv* env, jobject, jobject buffer,
+ jint index) {
+ NPE_CHECK_RETURN_ZERO(env, buffer);
+ const void* fontPtr = env->GetDirectBufferAddress(buffer);
+ if (fontPtr == nullptr) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
+ return nullptr;
+ }
+ jlong fontSize = env->GetDirectBufferCapacity(buffer);
+ if (fontSize <= 0) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "buffer size must not be zero or negative");
+ return nullptr;
+ }
+ minikin::FontFileParser parser(fontPtr, fontSize, index);
+ std::optional<std::string> psName = parser.getPostScriptName();
+ if (!psName.has_value()) {
+ return nullptr; // null
+ }
+ return env->NewStringUTF(psName->c_str());
+}
+///////////////////////////////////////////////////////////////////////////////
+
static const JNINativeMethod gFontBuilderMethods[] = {
{ "nInitBuilder", "()J", (void*) Font_Builder_initBuilder },
{ "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis },
@@ -254,13 +300,21 @@
{ "nGetReleaseFunc", "()J", (void*) FontBufferHelper_getReleaseFunc },
};
+static const JNINativeMethod gFontFileUtilMethods[] = {
+ { "nGetFontRevision", "(Ljava/nio/ByteBuffer;I)J", (void*) FontFileUtil_getFontRevision },
+ { "nGetFontPostScriptName", "(Ljava/nio/ByteBuffer;I)Ljava/lang/String;",
+ (void*) FontFileUtil_getFontPostScriptName },
+};
+
int register_android_graphics_fonts_Font(JNIEnv* env) {
return RegisterMethodsOrDie(env, "android/graphics/fonts/Font$Builder", gFontBuilderMethods,
NELEM(gFontBuilderMethods)) +
RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
NELEM(gFontMethods)) +
RegisterMethodsOrDie(env, "android/graphics/fonts/NativeFontBufferHelper",
- gFontBufferHelperMethods, NELEM(gFontBufferHelperMethods));
+ gFontBufferHelperMethods, NELEM(gFontBufferHelperMethods)) +
+ RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods,
+ NELEM(gFontFileUtilMethods));
}
namespace fonts {
diff --git a/libs/hwui/pipeline/skia/AnimatedDrawables.h b/libs/hwui/pipeline/skia/AnimatedDrawables.h
index 3142d92..7859145 100644
--- a/libs/hwui/pipeline/skia/AnimatedDrawables.h
+++ b/libs/hwui/pipeline/skia/AnimatedDrawables.h
@@ -61,13 +61,13 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect)
+ const SkRuntimeShaderBuilder& effectBuilder)
: mX(x)
, mY(y)
, mRadius(radius)
, mPaint(paint)
, mProgress(progress)
- , mRuntimeEffectBuilder(std::move(runtimeEffect)) {}
+ , mRuntimeEffectBuilder(effectBuilder) {}
protected:
virtual SkRect onGetBounds() override {
@@ -83,7 +83,7 @@
}
SkRuntimeShaderBuilder::BuilderUniform radiusU =
- mRuntimeEffectBuilder.uniform("in_maxRadius");
+ mRuntimeEffectBuilder.uniform("in_radius");
if (radiusU.fVar != nullptr) {
radiusU = mRadius->value;
}
diff --git a/libs/hwui/pipeline/skia/DumpOpsCanvas.h b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
index 26ff8bf..3580bed 100644
--- a/libs/hwui/pipeline/skia/DumpOpsCanvas.h
+++ b/libs/hwui/pipeline/skia/DumpOpsCanvas.h
@@ -29,7 +29,7 @@
*/
class DumpOpsCanvas : public SkCanvas {
public:
- DumpOpsCanvas(std::ostream& output, int level, SkiaDisplayList& displayList)
+ DumpOpsCanvas(std::ostream& output, int level, const SkiaDisplayList& displayList)
: mOutput(output)
, mLevel(level)
, mDisplayList(displayList)
@@ -127,7 +127,7 @@
}
private:
- RenderNodeDrawable* getRenderNodeDrawable(SkDrawable* drawable) {
+ const RenderNodeDrawable* getRenderNodeDrawable(SkDrawable* drawable) {
for (auto& child : mDisplayList.mChildNodes) {
if (drawable == &child) {
return &child;
@@ -147,7 +147,7 @@
std::ostream& mOutput;
int mLevel;
- SkiaDisplayList& mDisplayList;
+ const SkiaDisplayList& mDisplayList;
std::string mIdent;
};
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index 1473b3e..070a765 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -61,12 +61,11 @@
SkAutoCanvasRestore acr(canvas, true);
SkMatrix nodeMatrix;
mat4 hwuiMatrix(child.getRecordedMatrix());
- auto childNode = child.getRenderNode();
+ const RenderNode* childNode = child.getRenderNode();
childNode->applyViewPropertyTransforms(hwuiMatrix);
hwuiMatrix.copyTo(nodeMatrix);
canvas->concat(nodeMatrix);
- SkiaDisplayList* childDisplayList = static_cast<SkiaDisplayList*>(
- (const_cast<DisplayList*>(childNode->getDisplayList())));
+ const SkiaDisplayList* childDisplayList = childNode->getDisplayList().asSkiaDl();
if (childDisplayList) {
drawBackwardsProjectedNodes(canvas, *childDisplayList, nestLevel + 1);
}
@@ -144,7 +143,7 @@
return;
}
- SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList();
+ SkiaDisplayList* displayList = renderNode->getDisplayList().asSkiaDl();
SkAutoCanvasRestore acr(canvas, true);
const RenderProperties& properties = this->getNodeProperties();
@@ -213,14 +212,14 @@
if (mComposeLayer) {
setViewProperties(properties, canvas, &alphaMultiplier);
}
- SkiaDisplayList* displayList = (SkiaDisplayList*)mRenderNode->getDisplayList();
+ SkiaDisplayList* displayList = mRenderNode->getDisplayList().asSkiaDl();
displayList->mParentMatrix = canvas->getTotalMatrix();
// TODO should we let the bound of the drawable do this for us?
const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
bool quickRejected = properties.getClipToBounds() && canvas->quickReject(bounds);
if (!quickRejected) {
- SkiaDisplayList* displayList = (SkiaDisplayList*)renderNode->getDisplayList();
+ SkiaDisplayList* displayList = renderNode->getDisplayList().asSkiaDl();
const LayerProperties& layerProperties = properties.layerProperties();
// composing a hardware layer
if (renderNode->getLayerSurface() && mComposeLayer) {
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index c63f5d3..e6c6e10 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -172,7 +172,7 @@
new (&allocator) LinearAllocator();
}
-void SkiaDisplayList::output(std::ostream& output, uint32_t level) {
+void SkiaDisplayList::output(std::ostream& output, uint32_t level) const {
DumpOpsCanvas canvas(output, level, *this);
mDisplayList.draw(&canvas);
}
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index f2f19ba..483264f 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -142,7 +142,7 @@
void draw(SkCanvas* canvas) { mDisplayList.draw(canvas); }
- void output(std::ostream& output, uint32_t level);
+ void output(std::ostream& output, uint32_t level) const;
LinearAllocator allocator;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 6e7493c..d14dc36 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -98,7 +98,7 @@
continue;
}
SkASSERT(layerNode->getLayerSurface());
- SkiaDisplayList* displayList = (SkiaDisplayList*)layerNode->getDisplayList();
+ SkiaDisplayList* displayList = layerNode->getDisplayList().asSkiaDl();
if (!displayList || displayList->isEmpty()) {
ALOGE("%p drawLayers(%s) : missing drawable", layerNode, layerNode->getName());
return;
@@ -288,7 +288,7 @@
// recurse through the rendernode's children, add any nodes which are layers to the queue.
static void collectLayers(RenderNode* node, LayerUpdateQueue* layers) {
- SkiaDisplayList* dl = (SkiaDisplayList*)node->getDisplayList();
+ SkiaDisplayList* dl = node->getDisplayList().asSkiaDl();
if (dl) {
const auto& prop = node->properties();
if (node->hasLayer()) {
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 7faebda..9e91dff 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -55,11 +55,11 @@
SkiaCanvas::reset(&mRecorder);
}
-uirenderer::DisplayList* SkiaRecordingCanvas::finishRecording() {
+uirenderer::DisplayList SkiaRecordingCanvas::finishRecording() {
// close any existing chunks if necessary
enableZ(false);
mRecorder.restoreToCount(1);
- return mDisplayList.release();
+ return uirenderer::DisplayList(std::move(mDisplayList));
}
// ----------------------------------------------------------------------------
@@ -90,9 +90,9 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) {
+ const SkRuntimeShaderBuilder& effectBuilder) {
drawDrawable(mDisplayList->allocateDrawable<AnimatedRipple>(x, y, radius, paint, progress,
- runtimeEffect));
+ effectBuilder));
}
void SkiaRecordingCanvas::enableZ(bool enableZ) {
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 622df43..32c1791 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -43,7 +43,7 @@
initDisplayList(renderNode, width, height);
}
- virtual uirenderer::DisplayList* finishRecording() override;
+ virtual uirenderer::DisplayList finishRecording() override;
virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) override;
virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) override;
@@ -71,7 +71,7 @@
uirenderer::CanvasPropertyPrimitive* radius,
uirenderer::CanvasPropertyPaint* paint,
uirenderer::CanvasPropertyPrimitive* progress,
- sk_sp<SkRuntimeEffect> runtimeEffect) override;
+ const SkRuntimeShaderBuilder& effectBuilder) override;
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 1333b92..3e7ce36 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -27,6 +27,8 @@
#include <vk/GrVkExtensions.h>
#include <vk/GrVkTypes.h>
+#include <cstring>
+
#include "Properties.h"
#include "RenderThread.h"
#include "renderstate/RenderState.h"
@@ -53,6 +55,19 @@
}
}
+GrVkGetProc VulkanManager::sSkiaGetProp = [](const char* proc_name, VkInstance instance,
+ VkDevice device) {
+ if (device != VK_NULL_HANDLE) {
+ if (strcmp("vkQueueSubmit", proc_name) == 0) {
+ return (PFN_vkVoidFunction)VulkanManager::interceptedVkQueueSubmit;
+ } else if (strcmp("vkQueueWaitIdle", proc_name) == 0) {
+ return (PFN_vkVoidFunction)VulkanManager::interceptedVkQueueWaitIdle;
+ }
+ return vkGetDeviceProcAddr(device, proc_name);
+ }
+ return vkGetInstanceProcAddr(instance, proc_name);
+};
+
#define GET_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vk" #F)
#define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F)
#define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F)
@@ -83,7 +98,6 @@
}
mGraphicsQueue = VK_NULL_HANDLE;
- mAHBUploadQueue = VK_NULL_HANDLE;
mDevice = VK_NULL_HANDLE;
mPhysicalDevice = VK_NULL_HANDLE;
mInstance = VK_NULL_HANDLE;
@@ -185,7 +199,6 @@
for (uint32_t i = 0; i < queueCount; i++) {
if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
mGraphicsQueueIndex = i;
- LOG_ALWAYS_FATAL_IF(queueProps[i].queueCount < 2);
break;
}
}
@@ -210,14 +223,7 @@
LOG_ALWAYS_FATAL_IF(!hasKHRSwapchainExtension);
}
- auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
- if (device != VK_NULL_HANDLE) {
- return vkGetDeviceProcAddr(device, proc_name);
- }
- return vkGetInstanceProcAddr(instance, proc_name);
- };
-
- grExtensions.init(getProc, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
+ grExtensions.init(sSkiaGetProp, mInstance, mPhysicalDevice, mInstanceExtensions.size(),
mInstanceExtensions.data(), mDeviceExtensions.size(),
mDeviceExtensions.data());
@@ -289,7 +295,7 @@
queueNextPtr, // pNext
0, // VkDeviceQueueCreateFlags
mGraphicsQueueIndex, // queueFamilyIndex
- 2, // queueCount
+ 1, // queueCount
queuePriorities, // pQueuePriorities
};
@@ -344,7 +350,6 @@
this->setupDevice(mExtensions, mPhysicalDeviceFeatures2);
mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
- mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 1, &mAHBUploadQueue);
if (Properties::enablePartialUpdates && Properties::useBufferAge) {
mSwapBehavior = SwapBehavior::BufferAge;
@@ -353,24 +358,17 @@
sk_sp<GrDirectContext> VulkanManager::createContext(const GrContextOptions& options,
ContextType contextType) {
- auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
- if (device != VK_NULL_HANDLE) {
- return vkGetDeviceProcAddr(device, proc_name);
- }
- return vkGetInstanceProcAddr(instance, proc_name);
- };
GrVkBackendContext backendContext;
backendContext.fInstance = mInstance;
backendContext.fPhysicalDevice = mPhysicalDevice;
backendContext.fDevice = mDevice;
- backendContext.fQueue = (contextType == ContextType::kRenderThread) ? mGraphicsQueue
- : mAHBUploadQueue;
+ backendContext.fQueue = mGraphicsQueue;
backendContext.fGraphicsQueueIndex = mGraphicsQueueIndex;
backendContext.fMaxAPIVersion = mAPIVersion;
backendContext.fVkExtensions = &mExtensions;
backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
- backendContext.fGetProc = std::move(getProc);
+ backendContext.fGetProc = sSkiaGetProp;
return GrDirectContext::MakeVulkan(backendContext, options);
}
@@ -530,6 +528,8 @@
ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
} else {
ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");
+
+ std::lock_guard<std::mutex> lock(mGraphicsQueueMutex);
mQueueWaitIdle(mGraphicsQueue);
}
destroy_semaphore(destroyInfo);
@@ -540,6 +540,7 @@
void VulkanManager::destroySurface(VulkanSurface* surface) {
// Make sure all submit commands have finished before starting to destroy objects.
if (VK_NULL_HANDLE != mGraphicsQueue) {
+ std::lock_guard<std::mutex> lock(mGraphicsQueueMutex);
mQueueWaitIdle(mGraphicsQueue);
}
mDeviceWaitIdle(mDevice);
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 7a77466..121afc9 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -17,6 +17,10 @@
#ifndef VULKANMANAGER_H
#define VULKANMANAGER_H
+#include <functional>
+#include <mutex>
+
+#include "vulkan/vulkan_core.h"
#if !defined(VK_USE_PLATFORM_ANDROID_KHR)
#define VK_USE_PLATFORM_ANDROID_KHR
#endif
@@ -161,8 +165,25 @@
VkDevice mDevice = VK_NULL_HANDLE;
uint32_t mGraphicsQueueIndex;
+
+ std::mutex mGraphicsQueueMutex;
VkQueue mGraphicsQueue = VK_NULL_HANDLE;
- VkQueue mAHBUploadQueue = VK_NULL_HANDLE;
+
+ static VKAPI_ATTR VkResult interceptedVkQueueSubmit(VkQueue queue, uint32_t submitCount,
+ const VkSubmitInfo* pSubmits,
+ VkFence fence) {
+ sp<VulkanManager> manager = VulkanManager::getInstance();
+ std::lock_guard<std::mutex> lock(manager->mGraphicsQueueMutex);
+ return manager->mQueueSubmit(queue, submitCount, pSubmits, fence);
+ }
+
+ static VKAPI_ATTR VkResult interceptedVkQueueWaitIdle(VkQueue queue) {
+ sp<VulkanManager> manager = VulkanManager::getInstance();
+ std::lock_guard<std::mutex> lock(manager->mGraphicsQueueMutex);
+ return manager->mQueueWaitIdle(queue);
+ }
+
+ static GrVkGetProc sSkiaGetProp;
// Variables saved to populate VkFunctorInitParams.
static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0);
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index c1d8b76..ba6e8ee 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -50,12 +50,12 @@
ADD_FAILURE() << "ClipState not a rect"; \
}
-#define INNER_PIPELINE_TEST(test_case_name, test_name, pipeline, functionCall) \
- TEST(test_case_name, test_name##_##pipeline) { \
- RenderPipelineType oldType = Properties::getRenderPipelineType(); \
- Properties::overrideRenderPipelineType(RenderPipelineType::pipeline); \
- functionCall; \
- Properties::overrideRenderPipelineType(oldType); \
+#define INNER_PIPELINE_TEST(test_case_name, test_name, pipeline, functionCall) \
+ TEST(test_case_name, test_name##_##pipeline) { \
+ RenderPipelineType oldType = Properties::getRenderPipelineType(); \
+ Properties::overrideRenderPipelineType(RenderPipelineType::pipeline, true); \
+ functionCall; \
+ Properties::overrideRenderPipelineType(oldType, true); \
};
#define INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, pipeline) \
@@ -67,29 +67,27 @@
* Like gtest's TEST, but runs on the RenderThread, and 'renderThread' is passed, in top level scope
* (for e.g. accessing its RenderState)
*/
-#define RENDERTHREAD_TEST(test_case_name, test_name) \
- class test_case_name##_##test_name##_RenderThreadTest { \
- public: \
- static void doTheThing(renderthread::RenderThread& renderThread); \
- }; \
- INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
- /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \
- /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \
- void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \
+#define RENDERTHREAD_TEST(test_case_name, test_name) \
+ class test_case_name##_##test_name##_RenderThreadTest { \
+ public: \
+ static void doTheThing(renderthread::RenderThread& renderThread); \
+ }; \
+ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
+ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); \
+ void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \
renderthread::RenderThread& renderThread)
/**
* Like RENDERTHREAD_TEST, but only runs with the Skia RenderPipelineTypes
*/
-#define RENDERTHREAD_SKIA_PIPELINE_TEST(test_case_name, test_name) \
- class test_case_name##_##test_name##_RenderThreadTest { \
- public: \
- static void doTheThing(renderthread::RenderThread& renderThread); \
- }; \
- INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
- /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \
- /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \
- void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \
+#define RENDERTHREAD_SKIA_PIPELINE_TEST(test_case_name, test_name) \
+ class test_case_name##_##test_name##_RenderThreadTest { \
+ public: \
+ static void doTheThing(renderthread::RenderThread& renderThread); \
+ }; \
+ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \
+ INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); \
+ void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \
renderthread::RenderThread& renderThread)
/**
@@ -212,7 +210,8 @@
int left, int top, int right, int bottom,
std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)>
setup,
- const char* name = nullptr, skiapipeline::SkiaDisplayList* displayList = nullptr) {
+ const char* name = nullptr,
+ std::unique_ptr<skiapipeline::SkiaDisplayList> displayList = nullptr) {
sp<RenderNode> node = new RenderNode();
if (name) {
node->setName(name);
@@ -220,7 +219,7 @@
RenderProperties& props = node->mutateStagingProperties();
props.setLeftTopRightBottom(left, top, right, bottom);
if (displayList) {
- node->setStagingDisplayList(displayList);
+ node->setStagingDisplayList(DisplayList(std::move(displayList)));
}
if (setup) {
std::unique_ptr<skiapipeline::SkiaRecordingCanvas> canvas(
@@ -348,13 +347,11 @@
node->mNeedsDisplayListSync = false;
node->syncDisplayList(observer, nullptr);
}
- auto displayList = node->getDisplayList();
+ auto& displayList = node->getDisplayList();
if (displayList) {
- for (auto&& childDr :
- static_cast<skiapipeline::SkiaDisplayList*>(const_cast<DisplayList*>(displayList))
- ->mChildNodes) {
- syncHierarchyPropertiesAndDisplayListImpl(childDr.getRenderNode());
- }
+ displayList.updateChildren([](RenderNode* child) {
+ syncHierarchyPropertiesAndDisplayListImpl(child);
+ });
}
}
diff --git a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
index d393c69..ade1ddd 100644
--- a/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
+++ b/libs/hwui/tests/microbench/DisplayListCanvasBench.cpp
@@ -45,19 +45,19 @@
void BM_DisplayListCanvas_record_empty(benchmark::State& benchState) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
while (benchState.KeepRunning()) {
canvas->resetRecording(100, 100);
benchmark::DoNotOptimize(canvas.get());
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_record_empty);
void BM_DisplayListCanvas_record_saverestore(benchmark::State& benchState) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
while (benchState.KeepRunning()) {
canvas->resetRecording(100, 100);
@@ -66,20 +66,20 @@
benchmark::DoNotOptimize(canvas.get());
canvas->restore();
canvas->restore();
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_record_saverestore);
void BM_DisplayListCanvas_record_translate(benchmark::State& benchState) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
while (benchState.KeepRunning()) {
canvas->resetRecording(100, 100);
canvas->scale(10, 10);
benchmark::DoNotOptimize(canvas.get());
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_record_translate);
@@ -92,7 +92,7 @@
*/
void BM_DisplayListCanvas_record_simpleBitmapView(benchmark::State& benchState) {
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
Paint rectPaint;
sk_sp<Bitmap> iconBitmap(TestUtils::createBitmap(80, 80));
@@ -111,7 +111,7 @@
canvas->restore();
}
benchmark::DoNotOptimize(canvas.get());
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_record_simpleBitmapView);
@@ -122,7 +122,7 @@
});
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
while (benchState.KeepRunning()) {
canvas->resetRecording(200, 200);
@@ -143,7 +143,7 @@
canvas->enableZ(false);
canvas->restoreToCount(clipRestoreCount);
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
}
}
BENCHMARK(BM_DisplayListCanvas_basicViewGroupDraw)->Arg(1)->Arg(5)->Arg(10);
diff --git a/libs/hwui/tests/microbench/RenderNodeBench.cpp b/libs/hwui/tests/microbench/RenderNodeBench.cpp
index 011939a..dd3f737 100644
--- a/libs/hwui/tests/microbench/RenderNodeBench.cpp
+++ b/libs/hwui/tests/microbench/RenderNodeBench.cpp
@@ -16,6 +16,7 @@
#include <benchmark/benchmark.h>
+#include "hwui/Canvas.h"
#include "RenderNode.h"
using namespace android;
@@ -34,7 +35,7 @@
void BM_RenderNode_recordSimple(benchmark::State& state) {
sp<RenderNode> node = new RenderNode();
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
while (state.KeepRunning()) {
canvas->resetRecording(100, 100, node.get());
@@ -47,12 +48,12 @@
void BM_RenderNode_recordSimpleWithReuse(benchmark::State& state) {
sp<RenderNode> node = new RenderNode();
std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100));
- delete canvas->finishRecording();
+ static_cast<void>(canvas->finishRecording());
while (state.KeepRunning()) {
canvas->resetRecording(100, 100, node.get());
canvas->drawColor(0x00000000, SkBlendMode::kSrcOver);
- canvas->finishRecording()->reuseDisplayList(node.get());
+ canvas->finishRecording().clear(node.get());
}
}
BENCHMARK(BM_RenderNode_recordSimpleWithReuse);
\ No newline at end of file
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 4659a92..61bd646 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -326,7 +326,7 @@
// Check that the VD is in the dislay list, and the layer update queue contains the correct
// damage rect.
- EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
+ EXPECT_TRUE(rootNode->getDisplayList().hasVectorDrawables());
ASSERT_FALSE(info.layerUpdateQueue->entries().empty());
EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index c63f008..801a294 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -38,12 +38,13 @@
}
TEST(SkiaDisplayList, reset) {
- std::unique_ptr<SkiaDisplayList> skiaDL;
+ DisplayList displayList;
{
SkiaRecordingCanvas canvas{nullptr, 1, 1};
canvas.drawColor(0, SkBlendMode::kSrc);
- skiaDL.reset(canvas.finishRecording());
+ displayList = canvas.finishRecording();
}
+ SkiaDisplayList* skiaDL = displayList.asSkiaDl();
SkCanvas dummyCanvas;
RenderNodeDrawable drawable(nullptr, &dummyCanvas);
diff --git a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java
index bf0cef0..18cfce5 100644
--- a/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java
+++ b/libs/usb/tests/AccessoryChat/src/com/android/accessorychat/AccessoryChat.java
@@ -83,7 +83,7 @@
super.onCreate(savedInstanceState);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
- mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
+ mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_MUTABLE_UNAUDITED);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
diff --git a/location/java/android/location/CorrelationVector.java b/location/java/android/location/CorrelationVector.java
new file mode 100644
index 0000000..eca35dd
--- /dev/null
+++ b/location/java/android/location/CorrelationVector.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Contains info about the correlation output of incoming GNSS signal and a local copy of
+ * its corresponding spreading code at a given frequency offset.
+ *
+ * @hide
+ */
+@SystemApi
+public final class CorrelationVector implements Parcelable {
+
+ private final double mSamplingWidthMeters;
+ private final double mSamplingStartMeters;
+ private final int mFrequencyOffsetMetersPerSecond;
+ @NonNull private final int[] mMagnitude;
+
+ /**
+ * Returns the space between correlation samples in meters.
+ */
+ @FloatRange(from = 0.0f, fromInclusive = false)
+ public double getSamplingWidthMeters() {
+ return mSamplingWidthMeters;
+ }
+
+ /**
+ * Returns the offset of the first sampling bin in meters.
+ *
+ * <p>The following sampling bins are located at positive offsets from this value as follows:
+ * samplingStartMeters, samplingStartMeters + samplingWidthMeters, ... , samplingStartMeters +
+ * (magnitude.size-1) * samplingWidthMeters.
+ *
+ */
+ @FloatRange(from = 0.0f)
+ public double getSamplingStartMeters() {
+ return mSamplingStartMeters;
+ }
+
+ /**
+ * Returns the frequency offset from reported pseudorange rate for this CorrelationVector.
+ */
+ @IntRange(from = 0)
+ public int getFrequencyOffsetMetersPerSecond() {
+ return mFrequencyOffsetMetersPerSecond;
+ }
+
+ /**
+ * Returns the data array representing normalized correlation magnitude values.
+ *
+ * <p>The data are normalized correlation magnitude values from -1 to 1, the reported value must
+ * be encoded as signed 16 bit integer where 1 is represented by 32767 and -1 is represented
+ * by -32768.
+ *
+ */
+ @NonNull
+ public int[] getMagnitude() {
+ return mMagnitude.clone();
+ }
+
+ private CorrelationVector(Builder builder) {
+ Preconditions.checkNotNull(builder.mMagnitude, "Magnitude array must not be null");
+ Preconditions.checkArgumentPositive(builder.mMagnitude.length,
+ "Magnitude array must have non-zero length");
+ Preconditions.checkArgumentNonNegative(builder.mFrequencyOffsetMetersPerSecond,
+ "FrequencyOffsetMetersPerSecond must be non-negative (greater than or equal to 0)");
+ Preconditions.checkArgument(builder.mSamplingWidthMeters > 0.0,
+ "SamplingWidthMeters must be positive (greater than 0)");
+ Preconditions.checkArgument(builder.mSamplingStartMeters >= 0.0,
+ "SamplingStartMeters must be non-negative (greater than or equal to 0)");
+ mMagnitude = builder.mMagnitude;
+ mFrequencyOffsetMetersPerSecond = builder.mFrequencyOffsetMetersPerSecond;
+ mSamplingWidthMeters = builder.mSamplingWidthMeters;
+ mSamplingStartMeters = builder.mSamplingStartMeters;
+ }
+
+ private CorrelationVector(Parcel in) {
+ mSamplingWidthMeters = in.readDouble();
+ mSamplingStartMeters = in.readDouble();
+ mFrequencyOffsetMetersPerSecond = in.readInt();
+ mMagnitude = new int[in.readInt()];
+ in.readIntArray(mMagnitude);
+ }
+
+ /*
+ * Method definitions to support Parcelable operations.
+ */
+ public static final @NonNull Parcelable.Creator<CorrelationVector> CREATOR =
+ new Parcelable.Creator<CorrelationVector>() {
+ @Override
+ public CorrelationVector createFromParcel(Parcel parcel) {
+ return new CorrelationVector(parcel);
+ }
+
+ @Override
+ public CorrelationVector[] newArray(int size) {
+ return new CorrelationVector[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "CorrelationVector{"
+ + "FrequencyOffsetMetersPerSecond=" + mFrequencyOffsetMetersPerSecond
+ + ", SamplingWidthMeters=" + mSamplingWidthMeters
+ + ", SamplingStartMeters=" + mSamplingStartMeters
+ + ", Magnitude=" + Arrays.toString(mMagnitude)
+ + '}';
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeDouble(mSamplingWidthMeters);
+ dest.writeDouble(mSamplingStartMeters);
+ dest.writeInt(mFrequencyOffsetMetersPerSecond);
+ dest.writeInt(mMagnitude.length);
+ dest.writeIntArray(mMagnitude);
+ }
+
+ /**
+ * Returns true if this {@link CorrelationVector} is equivalent to the given object.
+ * Returns false otherwise.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (!(object instanceof CorrelationVector)) {
+ return false;
+ }
+ CorrelationVector c = (CorrelationVector) object;
+ return Arrays.equals(mMagnitude, c.getMagnitude())
+ && Double.compare(mSamplingWidthMeters, c.getSamplingWidthMeters()) == 0
+ && Double.compare(mSamplingStartMeters, c.getSamplingStartMeters()) == 0
+ && Integer.compare(mFrequencyOffsetMetersPerSecond,
+ c.getFrequencyOffsetMetersPerSecond()) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSamplingWidthMeters, mSamplingStartMeters,
+ mFrequencyOffsetMetersPerSecond, Arrays.hashCode(mMagnitude));
+ }
+
+ /**
+ * Builder class for CorrelationVector.
+ */
+ public static final class Builder {
+
+ private double mSamplingWidthMeters;
+ private double mSamplingStartMeters;
+ private int mFrequencyOffsetMetersPerSecond;
+ @NonNull private int[] mMagnitude;
+
+ /** Sets the space between correlation samples in meters. */
+ @NonNull
+ public Builder setSamplingWidthMeters(
+ @FloatRange(from = 0.0f, fromInclusive = false) double samplingWidthMeters) {
+ mSamplingWidthMeters = samplingWidthMeters;
+ return this;
+ }
+
+ /** Sets the offset of the first sampling bin in meters. */
+ @NonNull
+ public Builder setSamplingStartMeters(@FloatRange(from = 0.0f) double samplingStartMeters) {
+ mSamplingStartMeters = samplingStartMeters;
+ return this;
+ }
+
+ /** Sets the frequency offset from reported pseudorange rate for this CorrelationVector */
+ @NonNull
+ public Builder setFrequencyOffsetMetersPerSecond(
+ @IntRange(from = 0) int frequencyOffsetMetersPerSecond) {
+ mFrequencyOffsetMetersPerSecond = frequencyOffsetMetersPerSecond;
+ return this;
+ }
+
+ /** Sets the data array representing normalized correlation magnitude values. */
+ @NonNull
+ public Builder setMagnitude(@NonNull int[] magnitude) {
+ mMagnitude = magnitude;
+ return this;
+ }
+
+ /**
+ * Build CorrelationVector object.
+ *
+ * @return instance of CorrelationVector
+ */
+ @NonNull
+ public CorrelationVector build() {
+ return new CorrelationVector(this);
+ }
+ }
+}
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index 89a3bd5..a5e2815 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -57,6 +57,10 @@
public static final int TOP_HAL_CAPABILITY_MEASUREMENT_CORRECTIONS = 1024;
/** @hide */
public static final int TOP_HAL_CAPABILITY_ANTENNA_INFO = 2048;
+ /** @hide */
+ public static final int TOP_HAL_CAPABILITY_CORRELATION_VECTOR = 4096;
+ /** @hide */
+ public static final int TOP_HAL_CAPABILITY_SATELLITE_PVT = 8192;
/** @hide */
@IntDef(flag = true, prefix = {"TOP_HAL_CAPABILITY_"}, value = {TOP_HAL_CAPABILITY_SCHEDULING,
@@ -64,7 +68,9 @@
TOP_HAL_CAPABILITY_ON_DEMAND_TIME, TOP_HAL_CAPABILITY_GEOFENCING,
TOP_HAL_CAPABILITY_MEASUREMENTS, TOP_HAL_CAPABILITY_NAV_MESSAGES,
TOP_HAL_CAPABILITY_LOW_POWER_MODE, TOP_HAL_CAPABILITY_SATELLITE_BLOCKLIST,
- TOP_HAL_CAPABILITY_MEASUREMENT_CORRECTIONS, TOP_HAL_CAPABILITY_ANTENNA_INFO})
+ TOP_HAL_CAPABILITY_MEASUREMENT_CORRECTIONS, TOP_HAL_CAPABILITY_ANTENNA_INFO,
+ TOP_HAL_CAPABILITY_CORRELATION_VECTOR, TOP_HAL_CAPABILITY_SATELLITE_PVT})
+
@Retention(RetentionPolicy.SOURCE)
public @interface TopHalCapabilityFlags {}
@@ -294,6 +300,16 @@
}
/**
+ * Returns {@code true} if GNSS chipset supports satellite PVT, {@code false} otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean hasSatellitePvt() {
+ return (mTopFlags & TOP_HAL_CAPABILITY_SATELLITE_PVT) != 0;
+ }
+
+ /**
* Returns {@code true} if GNSS chipset supports measurement corrections, {@code false}
* otherwise.
*
@@ -324,6 +340,17 @@
}
/**
+ * Returns {@code true} if GNSS chipset supports correlation vectors as part of measurements
+ * outputs, {@code false} otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean hasMeasurementCorrelationVectors() {
+ return (mTopFlags & TOP_HAL_CAPABILITY_CORRELATION_VECTOR) != 0;
+ }
+
+ /**
* Returns {@code true} if GNSS chipset supports line-of-sight satellite identification
* measurement corrections, {@code false} otherwise.
*
@@ -511,12 +538,18 @@
if (hasSatelliteBlocklist()) {
builder.append("SATELLITE_BLOCKLIST ");
}
+ if (hasSatellitePvt()) {
+ builder.append("SATELLITE_PVT ");
+ }
if (hasMeasurementCorrections()) {
builder.append("MEASUREMENT_CORRECTIONS ");
}
if (hasAntennaInfo()) {
builder.append("ANTENNA_INFO ");
}
+ if (hasMeasurementCorrelationVectors()) {
+ builder.append("MEASUREMENT_CORRELATION_VECTORS ");
+ }
if (hasMeasurementCorrectionsLosSats()) {
builder.append("LOS_SATS ");
}
@@ -674,6 +707,17 @@
}
/**
+ * Sets satellite PVT capability.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setHasSatellitePvt(boolean capable) {
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_SATELLITE_PVT, capable);
+ return this;
+ }
+
+ /**
* Sets measurement corrections capability.
*
* @hide
@@ -693,6 +737,17 @@
}
/**
+ * Sets correlation vector capability.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setHasMeasurementCorrelationVectors(boolean capable) {
+ mTopFlags = setFlag(mTopFlags, TOP_HAL_CAPABILITY_CORRELATION_VECTOR, capable);
+ return this;
+ }
+
+ /**
* Sets measurement corrections line-of-sight satellites capabilitity.
*
* @hide
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index bd46ffd..3d188c0 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -30,12 +30,17 @@
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
/**
* A class representing a GNSS satellite measurement, containing raw and computed information.
@@ -67,12 +72,16 @@
private double mFullInterSignalBiasUncertaintyNanos;
private double mSatelliteInterSignalBiasNanos;
private double mSatelliteInterSignalBiasUncertaintyNanos;
+ @Nullable private SatellitePvt mSatellitePvt;
+ @Nullable private Collection<CorrelationVector> mReadOnlyCorrelationVectors;
// The following enumerations must be in sync with the values declared in GNSS HAL.
private static final int HAS_NO_FLAGS = 0;
private static final int HAS_CODE_TYPE = (1 << 14);
private static final int HAS_BASEBAND_CN0 = (1 << 15);
+ private static final int HAS_SATELLITE_PVT = (1 << 20);
+ private static final int HAS_CORRELATION_VECTOR = (1 << 21);
/**
* The status of the multipath indicator.
@@ -169,8 +178,8 @@
* @hide
*/
@IntDef(flag = true, prefix = { "ADR_STATE_" }, value = {
- ADR_STATE_VALID, ADR_STATE_RESET, ADR_STATE_CYCLE_SLIP, ADR_STATE_HALF_CYCLE_RESOLVED,
- ADR_STATE_HALF_CYCLE_REPORTED
+ ADR_STATE_UNKNOWN, ADR_STATE_VALID, ADR_STATE_RESET, ADR_STATE_CYCLE_SLIP,
+ ADR_STATE_HALF_CYCLE_RESOLVED, ADR_STATE_HALF_CYCLE_REPORTED
})
@Retention(RetentionPolicy.SOURCE)
public @interface AdrState {}
@@ -274,6 +283,8 @@
mSatelliteInterSignalBiasNanos = measurement.mSatelliteInterSignalBiasNanos;
mSatelliteInterSignalBiasUncertaintyNanos =
measurement.mSatelliteInterSignalBiasUncertaintyNanos;
+ mSatellitePvt = measurement.mSatellitePvt;
+ mReadOnlyCorrelationVectors = measurement.mReadOnlyCorrelationVectors;
}
/**
@@ -1691,6 +1702,108 @@
resetFlag(HAS_SATELLITE_ISB_UNCERTAINTY);
}
+ /**
+ * Returns {@code true} if {@link #getSatellitePvt()} is available,
+ * {@code false} otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean hasSatellitePvt() {
+ return isFlagSet(HAS_SATELLITE_PVT);
+ }
+
+ /**
+ * Gets the Satellite PVT data.
+ *
+ * <p>The value is only available if {@link #hasSatellitePvt()} is
+ * {@code true}.
+ *
+ * @hide
+ */
+ @Nullable
+ @SystemApi
+ public SatellitePvt getSatellitePvt() {
+ return mSatellitePvt;
+ }
+
+ /**
+ * Sets the Satellite PVT.
+ *
+ * @hide
+ */
+ @TestApi
+ public void setSatellitePvt(@Nullable SatellitePvt satellitePvt) {
+ if (satellitePvt == null) {
+ resetSatellitePvt();
+ } else {
+ setFlag(HAS_SATELLITE_PVT);
+ mSatellitePvt = satellitePvt;
+ }
+ }
+
+ /**
+ * Resets the Satellite PVT.
+ *
+ * @hide
+ */
+ @TestApi
+ public void resetSatellitePvt() {
+ resetFlag(HAS_SATELLITE_PVT);
+ }
+
+ /**
+ * Returns {@code true} if {@link #getCorrelationVectors()} is available,
+ * {@code false} otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean hasCorrelationVectors() {
+ return isFlagSet(HAS_CORRELATION_VECTOR);
+ }
+
+ /**
+ * Gets read-only collection of CorrelationVector with each CorrelationVector corresponding to a
+ * frequency offset.
+ *
+ * <p>To represent correlation values over a 2D spaces (delay and frequency), a
+ * CorrelationVector is required per frequency offset, and each CorrelationVector contains
+ * correlation values at equally spaced spatial offsets.
+ *
+ * @hide
+ */
+ @Nullable
+ @SystemApi
+ public Collection<CorrelationVector> getCorrelationVectors() {
+ return mReadOnlyCorrelationVectors;
+ }
+
+ /**
+ * Sets the CorrelationVectors.
+ *
+ * @hide
+ */
+ @TestApi
+ public void setCorrelationVectors(@Nullable Collection<CorrelationVector> correlationVectors) {
+ if (correlationVectors == null || correlationVectors.isEmpty()) {
+ resetCorrelationVectors();
+ } else {
+ setFlag(HAS_CORRELATION_VECTOR);
+ mReadOnlyCorrelationVectors = Collections.unmodifiableCollection(correlationVectors);
+ }
+ }
+
+ /**
+ * Resets the CorrelationVectors.
+ *
+ * @hide
+ */
+ @TestApi
+ public void resetCorrelationVectors() {
+ resetFlag(HAS_CORRELATION_VECTOR);
+ mReadOnlyCorrelationVectors = null;
+ }
public static final @NonNull Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
@Override
@@ -1723,7 +1836,19 @@
gnssMeasurement.mFullInterSignalBiasUncertaintyNanos = parcel.readDouble();
gnssMeasurement.mSatelliteInterSignalBiasNanos = parcel.readDouble();
gnssMeasurement.mSatelliteInterSignalBiasUncertaintyNanos = parcel.readDouble();
-
+ if (gnssMeasurement.hasSatellitePvt()) {
+ ClassLoader classLoader = getClass().getClassLoader();
+ gnssMeasurement.mSatellitePvt = parcel.readParcelable(classLoader);
+ }
+ if (gnssMeasurement.hasCorrelationVectors()) {
+ CorrelationVector[] correlationVectorsArray =
+ new CorrelationVector[parcel.readInt()];
+ parcel.readTypedArray(correlationVectorsArray, CorrelationVector.CREATOR);
+ Collection<CorrelationVector> corrVecCollection =
+ Arrays.asList(correlationVectorsArray);
+ gnssMeasurement.mReadOnlyCorrelationVectors =
+ Collections.unmodifiableCollection(corrVecCollection);
+ }
return gnssMeasurement;
}
@@ -1761,6 +1886,16 @@
parcel.writeDouble(mFullInterSignalBiasUncertaintyNanos);
parcel.writeDouble(mSatelliteInterSignalBiasNanos);
parcel.writeDouble(mSatelliteInterSignalBiasUncertaintyNanos);
+ if (hasSatellitePvt()) {
+ parcel.writeParcelable(mSatellitePvt, flags);
+ }
+ if (hasCorrelationVectors()) {
+ int correlationVectorCount = mReadOnlyCorrelationVectors.size();
+ CorrelationVector[] correlationVectorArray =
+ mReadOnlyCorrelationVectors.toArray(new CorrelationVector[correlationVectorCount]);
+ parcel.writeInt(correlationVectorArray.length);
+ parcel.writeTypedArray(correlationVectorArray, flags);
+ }
}
@Override
@@ -1864,6 +1999,17 @@
: null));
}
+ if (hasSatellitePvt()) {
+ builder.append(mSatellitePvt.toString());
+ }
+
+ if (hasCorrelationVectors()) {
+ for (CorrelationVector correlationVector : mReadOnlyCorrelationVectors) {
+ builder.append(correlationVector.toString());
+ builder.append("\n");
+ }
+ }
+
return builder.toString();
}
@@ -1893,6 +2039,8 @@
resetFullInterSignalBiasUncertaintyNanos();
resetSatelliteInterSignalBiasNanos();
resetSatelliteInterSignalBiasUncertaintyNanos();
+ resetSatellitePvt();
+ resetCorrelationVectors();
}
private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurementRequest.java b/location/java/android/location/GnssMeasurementRequest.java
index 613f591..f509252 100644
--- a/location/java/android/location/GnssMeasurementRequest.java
+++ b/location/java/android/location/GnssMeasurementRequest.java
@@ -17,20 +17,38 @@
package android.location;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Objects;
+
/**
* This class contains extra parameters to pass in a GNSS measurement request.
*/
public final class GnssMeasurementRequest implements Parcelable {
+ private final boolean mCorrelationVectorOutputsEnabled;
private final boolean mFullTracking;
/**
* Creates a {@link GnssMeasurementRequest} with a full list of parameters.
*/
- private GnssMeasurementRequest(boolean fullTracking) {
+ private GnssMeasurementRequest(boolean fullTracking, boolean correlationVectorOutputsEnabled) {
mFullTracking = fullTracking;
+ mCorrelationVectorOutputsEnabled = correlationVectorOutputsEnabled;
+ }
+
+ /**
+ * Represents whether to enable correlation vector outputs.
+ *
+ * <p>If true, enable correlation vectors as part of the raw GNSS measurements outputs.
+ * If false, disable correlation vectors.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean isCorrelationVectorOutputsEnabled() {
+ return mCorrelationVectorOutputsEnabled;
}
/**
@@ -56,7 +74,7 @@
@Override
@NonNull
public GnssMeasurementRequest createFromParcel(@NonNull Parcel parcel) {
- return new GnssMeasurementRequest(parcel.readBoolean());
+ return new GnssMeasurementRequest(parcel.readBoolean(), parcel.readBoolean());
}
@Override
@@ -68,6 +86,7 @@
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeBoolean(mFullTracking);
+ parcel.writeBoolean(mCorrelationVectorOutputsEnabled);
}
@NonNull
@@ -78,6 +97,9 @@
if (mFullTracking) {
s.append("FullTracking");
}
+ if (mCorrelationVectorOutputsEnabled) {
+ s.append(", CorrelationVectorOutPuts");
+ }
s.append(']');
return s.toString();
}
@@ -90,13 +112,15 @@
GnssMeasurementRequest other = (GnssMeasurementRequest) obj;
if (mFullTracking != other.mFullTracking) return false;
-
+ if (mCorrelationVectorOutputsEnabled != other.mCorrelationVectorOutputsEnabled) {
+ return false;
+ }
return true;
}
@Override
public int hashCode() {
- return mFullTracking ? 1 : 0;
+ return Objects.hash(mFullTracking, mCorrelationVectorOutputsEnabled);
}
@Override
@@ -106,6 +130,7 @@
/** Builder for {@link GnssMeasurementRequest} */
public static final class Builder {
+ private boolean mCorrelationVectorOutputsEnabled;
private boolean mFullTracking;
/**
@@ -118,10 +143,25 @@
* Constructs a {@link Builder} instance by copying a {@link GnssMeasurementRequest}.
*/
public Builder(@NonNull GnssMeasurementRequest request) {
+ mCorrelationVectorOutputsEnabled = request.isCorrelationVectorOutputsEnabled();
mFullTracking = request.isFullTracking();
}
/**
+ * Set the value of whether to enable correlation vector outputs, which is false by default.
+ *
+ * <p>If true, enable correlation vectors as part of the raw GNSS measurements outputs.
+ * If false, disable correlation vectors.
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull public Builder setCorrelationVectorOutputsEnabled(boolean value) {
+ mCorrelationVectorOutputsEnabled = value;
+ return this;
+ }
+
+ /**
* Set the value of whether to enable full GNSS tracking, which is false by default.
*
* <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
@@ -146,7 +186,7 @@
/** Builds a {@link GnssMeasurementRequest} instance as specified by this builder. */
@NonNull
public GnssMeasurementRequest build() {
- return new GnssMeasurementRequest(mFullTracking);
+ return new GnssMeasurementRequest(mFullTracking, mCorrelationVectorOutputsEnabled);
}
}
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 2dc9eb4..0ce1ad0 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -3171,7 +3171,9 @@
for (GnssMeasurementRequest request : requests) {
if (request.isFullTracking()) {
builder.setFullTracking(true);
- break;
+ }
+ if (request.isCorrelationVectorOutputsEnabled()) {
+ builder.setCorrelationVectorOutputsEnabled(true);
}
}
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
index 1027f9c..a6a0e7a 100644
--- a/location/java/android/location/LocationManagerInternal.java
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -80,4 +80,12 @@
*/
// TODO: there is no reason for this to exist as part of any API. move all the logic into gnss
public abstract void sendNiResponse(int notifId, int userResponse);
+
+ /**
+ * Returns the GNSS provided time.
+ *
+ * @return LocationTime object that includes the current time, according to the GNSS location
+ * provider, and the elapsed nanos since boot the current time was computed at.
+ */
+ public abstract @Nullable LocationTime getGnssTimeMillis();
}
diff --git a/location/java/android/location/SatellitePvt.java b/location/java/android/location/SatellitePvt.java
new file mode 100644
index 0000000..144fa13
--- /dev/null
+++ b/location/java/android/location/SatellitePvt.java
@@ -0,0 +1,514 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.annotation.FloatRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that contains GNSS satellite position, velocity and time information at the
+ * signal transmission time {@link GnssMeasurement#getReceivedSvTimeNanos()}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SatellitePvt implements Parcelable {
+ private final PositionEcef mPositionEcef;
+ private final VelocityEcef mVelocityEcef;
+ private final ClockInfo mClockInfo;
+ private final double mIonoDelayMeters;
+ private final double mTropoDelayMeters;
+
+ /**
+ * Class containing estimates of the satellite position fields in ECEF coordinate frame.
+ */
+ public static final class PositionEcef implements Parcelable {
+ private final double mXMeters;
+ private final double mYMeters;
+ private final double mZMeters;
+ private final double mUreMeters;
+
+ public PositionEcef(
+ double xMeters,
+ double yMeters,
+ double zMeters,
+ double ureMeters) {
+ mXMeters = xMeters;
+ mYMeters = yMeters;
+ mZMeters = zMeters;
+ mUreMeters = ureMeters;
+ }
+
+ public static final @NonNull Creator<PositionEcef> CREATOR =
+ new Creator<PositionEcef>() {
+ @Override
+ public PositionEcef createFromParcel(Parcel in) {
+ return new PositionEcef(
+ in.readDouble(),
+ in.readDouble(),
+ in.readDouble(),
+ in.readDouble()
+ );
+ }
+
+ @Override
+ public PositionEcef[] newArray(int size) {
+ return new PositionEcef[size];
+ }
+ };
+
+ /**
+ * Returns the satellite position X in WGS84 ECEF (meters).
+ */
+ @FloatRange()
+ public double getXMeters() {
+ return mXMeters;
+ }
+
+ /**
+ * Returns the satellite position Y in WGS84 ECEF (meters).
+ */
+ @FloatRange()
+ public double getYMeters() {
+ return mYMeters;
+ }
+
+ /**
+ * Returns the satellite position Z in WGS84 ECEF (meters).
+ */
+ @FloatRange()
+ public double getZMeters() {
+ return mZMeters;
+ }
+
+ /**
+ * Returns the signal in Space User Range Error (URE) (meters).
+ */
+ @FloatRange(from = 0.0f, fromInclusive = false)
+ public double getUreMeters() {
+ return mUreMeters;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeDouble(mXMeters);
+ dest.writeDouble(mYMeters);
+ dest.writeDouble(mZMeters);
+ dest.writeDouble(mUreMeters);
+ }
+
+ @Override
+ public String toString() {
+ return "PositionEcef{"
+ + "xMeters=" + mXMeters
+ + ", yMeters=" + mYMeters
+ + ", zMeters=" + mZMeters
+ + ", ureMeters=" + mUreMeters
+ + "}";
+ }
+ }
+
+ /**
+ * Class containing estimates of the satellite velocity fields in the ECEF coordinate frame.
+ */
+ public static final class VelocityEcef implements Parcelable {
+ private final double mXMetersPerSecond;
+ private final double mYMetersPerSecond;
+ private final double mZMetersPerSecond;
+ private final double mUreRateMetersPerSecond;
+
+ public VelocityEcef(
+ double xMetersPerSecond,
+ double yMetersPerSecond,
+ double zMetersPerSecond,
+ double ureRateMetersPerSecond) {
+ mXMetersPerSecond = xMetersPerSecond;
+ mYMetersPerSecond = yMetersPerSecond;
+ mZMetersPerSecond = zMetersPerSecond;
+ mUreRateMetersPerSecond = ureRateMetersPerSecond;
+ }
+
+ public static final @NonNull Creator<VelocityEcef> CREATOR =
+ new Creator<VelocityEcef>() {
+ @Override
+ public VelocityEcef createFromParcel(Parcel in) {
+ return new VelocityEcef(
+ in.readDouble(),
+ in.readDouble(),
+ in.readDouble(),
+ in.readDouble()
+ );
+ }
+
+ @Override
+ public VelocityEcef[] newArray(int size) {
+ return new VelocityEcef[size];
+ }
+ };
+
+ /**
+ * Returns the satellite velocity X in WGS84 ECEF (meters per second).
+ */
+ @FloatRange()
+ public double getXMetersPerSecond() {
+ return mXMetersPerSecond;
+ }
+
+ /**
+ * Returns the satellite velocity Y in WGS84 ECEF (meters per second).
+ */
+ @FloatRange()
+ public double getYMetersPerSecond() {
+ return mYMetersPerSecond;
+ }
+
+ /**
+ *Returns the satellite velocity Z in WGS84 ECEF (meters per second).
+ */
+ @FloatRange()
+ public double getZMetersPerSecond() {
+ return mZMetersPerSecond;
+ }
+
+ /**
+ * Returns the signal in Space User Range Error Rate (URE Rate) (meters per second).
+ *
+ * It covers satellite velocity error and Satellite clock drift
+ * projected to the pseudorange rate measurements.
+ */
+ @FloatRange(from = 0.0f, fromInclusive = false)
+ public double getUreRateMetersPerSecond() {
+ return mUreRateMetersPerSecond;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeDouble(mXMetersPerSecond);
+ dest.writeDouble(mYMetersPerSecond);
+ dest.writeDouble(mZMetersPerSecond);
+ dest.writeDouble(mUreRateMetersPerSecond);
+ }
+
+ @Override
+ public String toString() {
+ return "VelocityEcef{"
+ + "xMetersPerSecond=" + mXMetersPerSecond
+ + ", yMetersPerSecond=" + mYMetersPerSecond
+ + ", zMetersPerSecond=" + mZMetersPerSecond
+ + ", ureRateMetersPerSecond=" + mUreRateMetersPerSecond
+ + "}";
+ }
+ }
+
+ /**
+ * Class containing estimates of the satellite clock info.
+ */
+ public static final class ClockInfo implements Parcelable {
+ private final double mHardwareCodeBiasMeters;
+ private final double mTimeCorrectionMeters;
+ private final double mClockDriftMetersPerSecond;
+
+ public ClockInfo(
+ double hardwareCodeBiasMeters,
+ double timeCorrectionMeters,
+ double clockDriftMetersPerSecond) {
+ mHardwareCodeBiasMeters = hardwareCodeBiasMeters;
+ mTimeCorrectionMeters = timeCorrectionMeters;
+ mClockDriftMetersPerSecond = clockDriftMetersPerSecond;
+ }
+
+ public static final @NonNull Creator<ClockInfo> CREATOR =
+ new Creator<ClockInfo>() {
+ @Override
+ public ClockInfo createFromParcel(Parcel in) {
+ return new ClockInfo(
+ in.readDouble(),
+ in.readDouble(),
+ in.readDouble()
+ );
+ }
+
+ @Override
+ public ClockInfo[] newArray(int size) {
+ return new ClockInfo[size];
+ }
+ };
+
+ /**
+ * Returns the satellite hardware code bias of the reported code type w.r.t
+ * ionosphere-free measurement in meters.
+ */
+ @FloatRange()
+ public double getHardwareCodeBiasMeters() {
+ return mHardwareCodeBiasMeters;
+ }
+
+ /**
+ * Returns the satellite time correction for ionospheric-free signal measurement
+ * (meters). The satellite clock correction for the given signal type
+ * = satTimeCorrectionMeters - satHardwareCodeBiasMeters.
+ */
+ @FloatRange()
+ public double getTimeCorrectionMeters() {
+ return mTimeCorrectionMeters;
+ }
+
+ /**
+ * Returns the satellite clock drift (meters per second).
+ */
+ @FloatRange()
+ public double getClockDriftMetersPerSecond() {
+ return mClockDriftMetersPerSecond;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeDouble(mHardwareCodeBiasMeters);
+ dest.writeDouble(mTimeCorrectionMeters);
+ dest.writeDouble(mClockDriftMetersPerSecond);
+ }
+
+ @Override
+ public String toString() {
+ return "ClockInfo{"
+ + "hardwareCodeBiasMeters=" + mHardwareCodeBiasMeters
+ + ", timeCorrectionMeters=" + mTimeCorrectionMeters
+ + ", clockDriftMetersPerSecond=" + mClockDriftMetersPerSecond
+ + "}";
+ }
+ }
+
+ private SatellitePvt(
+ @NonNull PositionEcef positionEcef,
+ @NonNull VelocityEcef velocityEcef,
+ @NonNull ClockInfo clockInfo,
+ double ionoDelayMeters,
+ double tropoDelayMeters) {
+ if (positionEcef == null) {
+ throw new IllegalArgumentException("Position Ecef cannot be null.");
+ }
+ if (velocityEcef == null) {
+ throw new IllegalArgumentException("Velocity Ecef cannot be null.");
+ }
+ if (clockInfo == null) {
+ throw new IllegalArgumentException("Clock Info cannot be null.");
+ }
+ mPositionEcef = positionEcef;
+ mVelocityEcef = velocityEcef;
+ mClockInfo = clockInfo;
+ mIonoDelayMeters = ionoDelayMeters;
+ mTropoDelayMeters = tropoDelayMeters;
+ }
+
+ /**
+ * Returns a {@link PositionEcef} object that contains estimates of the satellite
+ * position fields in ECEF coordinate frame.
+ */
+ @NonNull
+ public PositionEcef getPositionEcef() {
+ return mPositionEcef;
+ }
+
+ /**
+ * Returns a {@link VelocityEcef} object that contains estimates of the satellite
+ * velocity fields in the ECEF coordinate frame.
+ */
+ @NonNull
+ public VelocityEcef getVelocityEcef() {
+ return mVelocityEcef;
+ }
+
+ /**
+ * Returns a {@link ClockInfo} object that contains estimates of the satellite
+ * clock info.
+ */
+ @NonNull
+ public ClockInfo getClockInfo() {
+ return mClockInfo;
+ }
+
+ /**
+ * Returns the ionospheric delay in meters.
+ */
+ @FloatRange()
+ public double getIonoDelayMeters() {
+ return mIonoDelayMeters;
+ }
+
+ /**
+ * Returns the tropospheric delay in meters.
+ */
+ @FloatRange()
+ public double getTropoDelayMeters() {
+ return mTropoDelayMeters;
+ }
+
+ public static final @android.annotation.NonNull Creator<SatellitePvt> CREATOR =
+ new Creator<SatellitePvt>() {
+ @Override
+ @Nullable
+ public SatellitePvt createFromParcel(Parcel in) {
+ ClassLoader classLoader = getClass().getClassLoader();
+ PositionEcef positionEcef = in.readParcelable(classLoader);
+ VelocityEcef velocityEcef = in.readParcelable(classLoader);
+ ClockInfo clockInfo = in.readParcelable(classLoader);
+ double ionoDelayMeters = in.readDouble();
+ double tropoDelayMeters = in.readDouble();
+
+ return new SatellitePvt(
+ positionEcef,
+ velocityEcef,
+ clockInfo,
+ ionoDelayMeters,
+ tropoDelayMeters);
+ }
+
+ @Override
+ public SatellitePvt[] newArray(int size) {
+ return new SatellitePvt[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeParcelable(mPositionEcef, flags);
+ parcel.writeParcelable(mVelocityEcef, flags);
+ parcel.writeParcelable(mClockInfo, flags);
+ parcel.writeDouble(mIonoDelayMeters);
+ parcel.writeDouble(mTropoDelayMeters);
+ }
+
+ @Override
+ public String toString() {
+ return "SatellitePvt{"
+ + "PositionEcef=" + mPositionEcef
+ + ", VelocityEcef=" + mVelocityEcef
+ + ", ClockInfo=" + mClockInfo
+ + ", IonoDelayMeters=" + mIonoDelayMeters
+ + ", TropoDelayMeters=" + mTropoDelayMeters
+ + "}";
+ }
+
+ /**
+ * Builder class for SatellitePvt.
+ */
+ public static final class Builder {
+ private PositionEcef mPositionEcef;
+ private VelocityEcef mVelocityEcef;
+ private ClockInfo mClockInfo;
+ private double mIonoDelayMeters;
+ private double mTropoDelayMeters;
+
+ /**
+ * Set position ECEF.
+ *
+ * @param positionEcef position ECEF object
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setPositionEcef(
+ @NonNull PositionEcef positionEcef) {
+ mPositionEcef = positionEcef;
+ return this;
+ }
+
+ /**
+ * Set velocity ECEF.
+ *
+ * @param velocityEcef velocity ECEF object
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setVelocityEcef(
+ @NonNull VelocityEcef velocityEcef) {
+ mVelocityEcef = velocityEcef;
+ return this;
+ }
+
+ /**
+ * Set clock info.
+ *
+ * @param clockInfo clock info object
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setClockInfo(
+ @NonNull ClockInfo clockInfo) {
+ mClockInfo = clockInfo;
+ return this;
+ }
+
+ /**
+ * Set ionospheric delay in meters.
+ *
+ * @param ionoDelayMeters ionospheric delay (meters)
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setIonoDelayMeters(@FloatRange() double ionoDelayMeters) {
+ mIonoDelayMeters = ionoDelayMeters;
+ return this;
+ }
+
+ /**
+ * Set tropospheric delay in meters.
+ *
+ * @param tropoDelayMeters tropospheric delay (meters)
+ * @return Builder builder object
+ */
+ @NonNull
+ public Builder setTropoDelayMeters(@FloatRange() double tropoDelayMeters) {
+ mTropoDelayMeters = tropoDelayMeters;
+ return this;
+ }
+
+ /**
+ * Build SatellitePvt object.
+ *
+ * @return instance of SatellitePvt
+ */
+ @NonNull
+ public SatellitePvt build() {
+ return new SatellitePvt(mPositionEcef, mVelocityEcef, mClockInfo,
+ mIonoDelayMeters, mTropoDelayMeters);
+ }
+ }
+}
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index b545a83..aea93ce 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -94,6 +94,10 @@
*/
public static final String FUSED_PROVIDER = LocationManager.FUSED_PROVIDER;
+ private static final String EXTRA_KEY_COARSE_LOCATION = "coarseLocation";
+ private static final String EXTRA_KEY_NO_GPS_LOCATION = "noGPSLocation";
+ private static final String EXTRA_KEY_INDOOR_PROB = "indoorProbability";
+
final String mTag;
@Nullable final String mPackageName;
@Nullable final String mAttributionTag;
@@ -260,21 +264,7 @@
public void reportLocation(LocationResult locationResult) {
ILocationProviderManager manager = mManager;
if (manager != null) {
- locationResult = locationResult.map(location -> {
- // remove deprecated extras to save on serialization costs
- Bundle extras = location.getExtras();
- if (extras != null && (extras.containsKey("noGPSLocation")
- || extras.containsKey("coarseLocation"))) {
- location = new Location(location);
- extras = location.getExtras();
- extras.remove("noGPSLocation");
- extras.remove("coarseLocation");
- if (extras.isEmpty()) {
- location.setExtras(null);
- }
- }
- return location;
- });
+ locationResult = locationResult.map(this::cleanUpExtras);
try {
manager.onReportLocation(locationResult);
@@ -286,6 +276,33 @@
}
}
+ /**
+ * Remove deprecated/unnecessary extras to save on serialization costs.
+ *
+ * {@link #EXTRA_KEY_NO_GPS_LOCATION} and {@link #EXTRA_KEY_COARSE_LOCATION} are deprecated.
+ *
+ * {@link #EXTRA_KEY_INDOOR_PROB} should only be used in the framework.
+ */
+ private Location cleanUpExtras(Location location) {
+ Bundle extras = location.getExtras();
+ if (extras == null) {
+ return location;
+ }
+ if (extras.containsKey(EXTRA_KEY_NO_GPS_LOCATION)
+ || extras.containsKey(EXTRA_KEY_COARSE_LOCATION)
+ || extras.containsKey(EXTRA_KEY_INDOOR_PROB)) {
+ location = new Location(location);
+ extras = location.getExtras();
+ extras.remove(EXTRA_KEY_NO_GPS_LOCATION);
+ extras.remove(EXTRA_KEY_COARSE_LOCATION);
+ extras.remove(EXTRA_KEY_INDOOR_PROB);
+ if (extras.isEmpty()) {
+ location.setExtras(null);
+ }
+ }
+ return location;
+ }
+
protected void onInit() {
// call once so that providers designed for APIs pre-Q are not broken
onEnable();
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 367b784..000c34d 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3096,11 +3096,140 @@
* @see #playSoundEffect(int)
*/
public static final int FX_KEYPRESS_INVALID = 9;
+
+ /**
+ * Back sound
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_BACK = 10;
+
+ /**
+ * @hide Home sound
+ * Played by the framework when the home app becomes active if config_enableHomeSound is set to
+ * true. This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml.
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_HOME = 11;
+
+ /**
+ * @hide Fast scroll sound 1
+ * To be by the framework when a fast-scrolling is performed and
+ * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_FAST_SCROLL_1 = 12;
+
+ /**
+ * @hide Fast scroll sound 2
+ * To be by the framework when a fast-scrolling is performed and
+ * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_FAST_SCROLL_2 = 13;
+
+ /**
+ * @hide Fast scroll sound 3
+ * To be by the framework when a fast-scrolling is performed and
+ * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_FAST_SCROLL_3 = 14;
+
+ /**
+ * @hide Fast scroll sound 4
+ * To be by the framework when a fast-scrolling is performed and
+ * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * This is currently only used on TV devices.
+ * Note that this sound is only available if a sound file is specified in audio_assets.xml
+ * @see #playSoundEffect(int)
+ */
+ public static final int FX_FAST_SCROLL_4 = 15;
+
/**
* @hide Number of sound effects
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int NUM_SOUND_EFFECTS = 10;
+ public static final int NUM_SOUND_EFFECTS = 16;
+
+ /**
+ * @hide Number of fast scroll sound effects
+ */
+ public static final int NUM_FAST_SCROLL_SOUND_EFFECTS = 4;
+
+ /**
+ * @hide
+ * @param n a value in [0, {@link #NUM_FAST_SCROLL_SOUND_EFFECTS}[
+ * @return The id of a fast scroll sound effect or -1 if out of bounds
+ */
+ public static int getNthFastScrollSoundEffectId(int n) {
+ switch (n) {
+ case 0:
+ return FX_FAST_SCROLL_1;
+ case 1:
+ return FX_FAST_SCROLL_2;
+ case 2:
+ return FX_FAST_SCROLL_3;
+ case 3:
+ return FX_FAST_SCROLL_4;
+ default:
+ Log.w(TAG, "Invalid fast-scroll sound effect id: " + n);
+ return -1;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setFastScrollSoundEffectsEnabled(boolean enabled) {
+ try {
+ getService().setFastScrollSoundEffectsEnabled(enabled);
+ } catch (RemoteException e) {
+
+ }
+ }
+
+ /**
+ * @hide
+ * @return true if the fast scroll sound effects are enabled
+ */
+ public boolean areFastScrollSoundEffectsEnabled() {
+ try {
+ return getService().areFastScrollSoundEffectsEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * @param enabled
+ */
+ public void setHomeSoundEffectEnabled(boolean enabled) {
+ try {
+ getService().setHomeSoundEffectEnabled(enabled);
+ } catch (RemoteException e) {
+
+ }
+ }
+
+ /**
+ * @hide
+ * @return true if the home sound effect is enabled
+ */
+ public boolean isHomeSoundEffectEnabled() {
+ try {
+ return getService().isHomeSoundEffectEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/**
* Plays a sound effect (Key clicks, lid open/close...)
@@ -3115,10 +3244,11 @@
* {@link #FX_KEYPRESS_DELETE},
* {@link #FX_KEYPRESS_RETURN},
* {@link #FX_KEYPRESS_INVALID},
+ * {@link #FX_BACK},
* NOTE: This version uses the UI settings to determine
* whether sounds are heard or not.
*/
- public void playSoundEffect(int effectType) {
+ public void playSoundEffect(int effectType) {
if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
return;
}
@@ -3148,6 +3278,7 @@
* {@link #FX_KEYPRESS_DELETE},
* {@link #FX_KEYPRESS_RETURN},
* {@link #FX_KEYPRESS_INVALID},
+ * {@link #FX_BACK},
* @param userId The current user to pull sound settings from
* NOTE: This version uses the UI settings to determine
* whether sounds are heard or not.
@@ -3183,6 +3314,7 @@
* {@link #FX_KEYPRESS_DELETE},
* {@link #FX_KEYPRESS_RETURN},
* {@link #FX_KEYPRESS_INVALID},
+ * {@link #FX_BACK},
* @param volume Sound effect volume.
* The volume value is a raw scalar so UI controls should be scaled logarithmically.
* If a volume of -1 is specified, the AudioManager.STREAM_MUSIC stream volume minus 3dB will be used.
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index b6bb3a3..e32185a 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -348,4 +348,12 @@
oneway void unregisterCommunicationDeviceDispatcher(
ICommunicationDeviceDispatcher dispatcher);
+
+ boolean areFastScrollSoundEffectsEnabled();
+
+ oneway void setFastScrollSoundEffectsEnabled(boolean enabled);
+
+ boolean isHomeSoundEffectEnabled();
+
+ oneway void setHomeSoundEffectEnabled(boolean enabled);
}
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 9957975..582a28e 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -716,8 +716,9 @@
context.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE);
if (mTunerResourceManager != null) {
int[] clientId = new int[1];
- ResourceClientProfile profile =
- new ResourceClientProfile(tvInputServiceSessionId, priorityHint);
+ ResourceClientProfile profile = new ResourceClientProfile();
+ profile.tvInputSessionId = tvInputServiceSessionId;
+ profile.useCase = priorityHint;
mTunerResourceManager.registerClientProfile(
profile, context.getMainExecutor(), mResourceListener, clientId);
mClientId = clientId[0];
@@ -921,7 +922,9 @@
int[] sessionResourceHandle = new int[1];
sessionResourceHandle[0] = -1;
if (mTunerResourceManager != null) {
- CasSessionRequest casSessionRequest = new CasSessionRequest(mClientId, mCasSystemId);
+ CasSessionRequest casSessionRequest = new CasSessionRequest();
+ casSessionRequest.clientId = mClientId;
+ casSessionRequest.casSystemId = mCasSystemId;
if (!mTunerResourceManager
.requestCasSession(casSessionRequest, sessionResourceHandle)) {
throw new MediaCasException.InsufficientResourceException(
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index ae97a71..607c8f1 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -25,6 +25,7 @@
import android.graphics.SurfaceTexture;
import android.hardware.HardwareBuffer;
import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.metrics.PlaybackComponent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -1538,7 +1539,8 @@
</tbody>
</table>
*/
-final public class MediaCodec {
+final public class MediaCodec implements PlaybackComponent {
+
/**
* Per buffer metadata includes an offset and size specifying
* the range of valid data in the associated codec (output) buffer.
@@ -1680,6 +1682,7 @@
private MediaCodecInfo mCodecInfo;
private final Object mCodecInfoLock = new Object();
private MediaCrypto mCrypto;
+ private String mPlaybackId;
private static final int EVENT_CALLBACK = 1;
private static final int EVENT_SET_CALLBACK = 2;
@@ -1690,6 +1693,23 @@
private static final int CB_ERROR = 3;
private static final int CB_OUTPUT_FORMAT_CHANGE = 4;
+
+ /**
+ * @hide
+ */
+ @Override
+ public void setPlaybackId(@NonNull String playbackId) {
+ // TODO: add a native method to pass the ID to the native code for logging.
+ mPlaybackId = playbackId;
+ }
+ /**
+ * @hide
+ */
+ @Override
+ public String getPlaybackId() {
+ return mPlaybackId;
+ }
+
private class EventHandler extends Handler {
private MediaCodec mCodec;
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 60a0052..8d47ed1 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -48,7 +48,7 @@
* // build the PendingIntent for the remote control client
* Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
* mediaButtonIntent.setComponent(myEventReceiver);
- * PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
+ * PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
* // create and register the remote control client
* RemoteControlClient myRemoteControlClient = new RemoteControlClient(mediaPendingIntent);
* myAudioManager.registerRemoteControlClient(myRemoteControlClient);</pre>
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 221147d..0c73348 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -218,7 +218,7 @@
/** @return an error string if the format would not allow Privileged playbackCapture
* null otherwise
* @hide */
- public static String canBeUsedForPrivilegedCapture(AudioFormat format) {
+ public static String canBeUsedForPrivilegedMediaCapture(AudioFormat format) {
int sampleRate = format.getSampleRate();
if (sampleRate > PRIVILEDGED_CAPTURE_MAX_SAMPLE_RATE || sampleRate <= 0) {
return "Privileged audio capture sample rate " + sampleRate
@@ -448,8 +448,8 @@
}
}
}
- if (mRule.allowPrivilegedPlaybackCapture()) {
- String error = AudioMix.canBeUsedForPrivilegedCapture(mFormat);
+ if (mRule.allowPrivilegedMediaPlaybackCapture()) {
+ String error = AudioMix.canBeUsedForPrivilegedMediaCapture(mFormat);
if (error != null) {
throw new IllegalArgumentException(error);
}
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index de15313..1f07705 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -46,11 +46,11 @@
public class AudioMixingRule {
private AudioMixingRule(int mixType, ArrayList<AudioMixMatchCriterion> criteria,
- boolean allowPrivilegedPlaybackCapture,
+ boolean allowPrivilegedMediaPlaybackCapture,
boolean voiceCommunicationCaptureAllowed) {
mCriteria = criteria;
mTargetMixType = mixType;
- mAllowPrivilegedPlaybackCapture = allowPrivilegedPlaybackCapture;
+ mAllowPrivilegedPlaybackCapture = allowPrivilegedMediaPlaybackCapture;
mVoiceCommunicationCaptureAllowed = voiceCommunicationCaptureAllowed;
}
@@ -204,13 +204,17 @@
private final ArrayList<AudioMixMatchCriterion> mCriteria;
/** @hide */
public ArrayList<AudioMixMatchCriterion> getCriteria() { return mCriteria; }
+ /** Indicates that this rule is intended to capture media or game playback by a system component
+ * with permission CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT.
+ */
+ //TODO b/177061175: rename to mAllowPrivilegedMediaPlaybackCapture
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private boolean mAllowPrivilegedPlaybackCapture = false;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private boolean mVoiceCommunicationCaptureAllowed = false;
/** @hide */
- public boolean allowPrivilegedPlaybackCapture() {
+ public boolean allowPrivilegedMediaPlaybackCapture() {
return mAllowPrivilegedPlaybackCapture;
}
@@ -311,7 +315,7 @@
public static class Builder {
private ArrayList<AudioMixMatchCriterion> mCriteria;
private int mTargetMixType = AudioMix.MIX_TYPE_INVALID;
- private boolean mAllowPrivilegedPlaybackCapture = false;
+ private boolean mAllowPrivilegedMediaPlaybackCapture = false;
// This value should be set internally according to a permission check
private boolean mVoiceCommunicationCaptureAllowed = false;
@@ -434,7 +438,7 @@
* @return the same Builder instance.
*/
public @NonNull Builder allowPrivilegedPlaybackCapture(boolean allow) {
- mAllowPrivilegedPlaybackCapture = allow;
+ mAllowPrivilegedMediaPlaybackCapture = allow;
return this;
}
@@ -639,7 +643,7 @@
*/
public AudioMixingRule build() {
return new AudioMixingRule(mTargetMixType, mCriteria,
- mAllowPrivilegedPlaybackCapture, mVoiceCommunicationCaptureAllowed);
+ mAllowPrivilegedMediaPlaybackCapture, mVoiceCommunicationCaptureAllowed);
}
}
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 697d80c..ede68bd 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -97,7 +97,7 @@
dest.writeInt(mix.getFormat().getEncoding());
dest.writeInt(mix.getFormat().getChannelMask());
// write opt-out respect
- dest.writeBoolean(mix.getRule().allowPrivilegedPlaybackCapture());
+ dest.writeBoolean(mix.getRule().allowPrivilegedMediaPlaybackCapture());
// write voice communication capture allowed flag
dest.writeBoolean(mix.getRule().voiceCommunicationCaptureAllowed());
// write mix rules
@@ -172,7 +172,7 @@
textDump += " channels=0x";
textDump += Integer.toHexString(mix.getFormat().getChannelMask()).toUpperCase() + "\n";
textDump += " ignore playback capture opt out="
- + mix.getRule().allowPrivilegedPlaybackCapture() + "\n";
+ + mix.getRule().allowPrivilegedMediaPlaybackCapture() + "\n";
textDump += " allow voice communication capture="
+ mix.getRule().voiceCommunicationCaptureAllowed() + "\n";
// write mix rules
diff --git a/media/java/android/media/metrics/IPlaybackMetricsManager.aidl b/media/java/android/media/metrics/IPlaybackMetricsManager.aidl
index 47debe9..52d952c 100644
--- a/media/java/android/media/metrics/IPlaybackMetricsManager.aidl
+++ b/media/java/android/media/metrics/IPlaybackMetricsManager.aidl
@@ -16,7 +16,10 @@
package android.media.metrics;
+import android.media.metrics.NetworkEvent;
+import android.media.metrics.PlaybackErrorEvent;
import android.media.metrics.PlaybackMetrics;
+import android.media.metrics.PlaybackStateEvent;
/**
* Interface to the playback manager service.
@@ -25,4 +28,7 @@
interface IPlaybackMetricsManager {
void reportPlaybackMetrics(in String sessionId, in PlaybackMetrics metrics, int userId);
String getSessionId(int userId);
+ void reportNetworkEvent(in String sessionId, in NetworkEvent event, int userId);
+ void reportPlaybackErrorEvent(in String sessionId, in PlaybackErrorEvent event, int userId);
+ void reportPlaybackStateEvent(in String sessionId, in PlaybackStateEvent event, int userId);
}
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl b/media/java/android/media/metrics/NetworkEvent.aidl
similarity index 74%
copy from media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
copy to media/java/android/media/metrics/NetworkEvent.aidl
index 0e6fcde..2b7fa02 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
+++ b/media/java/android/media/metrics/NetworkEvent.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,11 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.media.metrics;
-/**
- * Information required to request a Tuner Lnb.
- *
- * @hide
- */
-parcelable TunerLnbRequest;
\ No newline at end of file
+parcelable NetworkEvent;
diff --git a/media/java/android/media/metrics/NetworkEvent.java b/media/java/android/media/metrics/NetworkEvent.java
new file mode 100644
index 0000000..a330bc0
--- /dev/null
+++ b/media/java/android/media/metrics/NetworkEvent.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.metrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Playback network event.
+ * @hide
+ */
+public final class NetworkEvent implements Parcelable {
+ public static final int NETWORK_TYPE_NONE = 0;
+ public static final int NETWORK_TYPE_OTHER = 1;
+ public static final int NETWORK_TYPE_WIFI = 2;
+ public static final int NETWORK_TYPE_ETHERNET = 3;
+ public static final int NETWORK_TYPE_2G = 4;
+ public static final int NETWORK_TYPE_3G = 5;
+ public static final int NETWORK_TYPE_4G = 6;
+ public static final int NETWORK_TYPE_5G_NSA = 7;
+ public static final int NETWORK_TYPE_5G_SA = 8;
+
+ private final int mType;
+ private final long mTimeSincePlaybackCreatedMillis;
+
+ /** @hide */
+ @IntDef(prefix = "NETWORK_TYPE_", value = {
+ NETWORK_TYPE_NONE,
+ NETWORK_TYPE_OTHER,
+ NETWORK_TYPE_WIFI,
+ NETWORK_TYPE_ETHERNET,
+ NETWORK_TYPE_2G,
+ NETWORK_TYPE_3G,
+ NETWORK_TYPE_4G,
+ NETWORK_TYPE_5G_NSA,
+ NETWORK_TYPE_5G_SA
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NetworkType {}
+
+ /**
+ * Network type to string.
+ */
+ public static String networkTypeToString(@NetworkType int value) {
+ switch (value) {
+ case NETWORK_TYPE_NONE:
+ return "NETWORK_TYPE_NONE";
+ case NETWORK_TYPE_OTHER:
+ return "NETWORK_TYPE_OTHER";
+ case NETWORK_TYPE_WIFI:
+ return "NETWORK_TYPE_WIFI";
+ case NETWORK_TYPE_ETHERNET:
+ return "NETWORK_TYPE_ETHERNET";
+ case NETWORK_TYPE_2G:
+ return "NETWORK_TYPE_2G";
+ case NETWORK_TYPE_3G:
+ return "NETWORK_TYPE_3G";
+ case NETWORK_TYPE_4G:
+ return "NETWORK_TYPE_4G";
+ case NETWORK_TYPE_5G_NSA:
+ return "NETWORK_TYPE_5G_NSA";
+ case NETWORK_TYPE_5G_SA:
+ return "NETWORK_TYPE_5G_SA";
+ default:
+ return Integer.toHexString(value);
+ }
+ }
+
+ /**
+ * Creates a new NetworkEvent.
+ *
+ * @hide
+ */
+ public NetworkEvent(@NetworkType int type, long timeSincePlaybackCreatedMillis) {
+ this.mType = type;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ @NetworkType
+ public int getType() {
+ return mType;
+ }
+
+ public long getTimeSincePlaybackCreatedMillis() {
+ return mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "NetworkEvent { "
+ + "type = " + mType + ", "
+ + "timeSincePlaybackCreatedMillis = " + mTimeSincePlaybackCreatedMillis
+ + " }";
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NetworkEvent that = (NetworkEvent) o;
+ return mType == that.mType
+ && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mType, mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ dest.writeInt(mType);
+ dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ /* package-private */ NetworkEvent(@NonNull android.os.Parcel in) {
+ int type = in.readInt();
+ long timeSincePlaybackCreatedMillis = in.readLong();
+
+ this.mType = type;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ public static final @NonNull Parcelable.Creator<NetworkEvent> CREATOR =
+ new Parcelable.Creator<NetworkEvent>() {
+ @Override
+ public NetworkEvent[] newArray(int size) {
+ return new NetworkEvent[size];
+ }
+
+ @Override
+ public NetworkEvent createFromParcel(@NonNull Parcel in) {
+ return new NetworkEvent(in);
+ }
+ };
+
+ /**
+ * A builder for {@link NetworkEvent}
+ */
+ public static final class Builder {
+ private int mType;
+ private long mTimeSincePlaybackCreatedMillis;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @hide
+ */
+ public Builder() {
+ }
+
+ /**
+ * Sets network type.
+ */
+ public @NonNull Builder setType(@NetworkType int value) {
+ mType = value;
+ return this;
+ }
+
+ /**
+ * Sets timestamp since the creation in milliseconds.
+ */
+ public @NonNull Builder setTimeSincePlaybackCreatedMillis(long value) {
+ mTimeSincePlaybackCreatedMillis = value;
+ return this;
+ }
+
+ /** Builds the instance. */
+ public @NonNull NetworkEvent build() {
+ NetworkEvent o = new NetworkEvent(
+ mType,
+ mTimeSincePlaybackCreatedMillis);
+ return o;
+ }
+ }
+}
diff --git a/media/java/android/media/metrics/PlaybackComponent.java b/media/java/android/media/metrics/PlaybackComponent.java
new file mode 100644
index 0000000..625dd0a
--- /dev/null
+++ b/media/java/android/media/metrics/PlaybackComponent.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.metrics;
+
+import android.annotation.NonNull;
+
+/**
+ * Interface for playback related components used by playback metrics.
+ * @hide
+ */
+public interface PlaybackComponent {
+
+ /**
+ * Sets the playback ID of the component.
+ */
+ void setPlaybackId(@NonNull String playbackId);
+
+ /**
+ * Gets playback ID.
+ */
+ @NonNull String getPlaybackId();
+}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl b/media/java/android/media/metrics/PlaybackErrorEvent.aidl
similarity index 74%
copy from media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
copy to media/java/android/media/metrics/PlaybackErrorEvent.aidl
index 0e6fcde..b0d6b4b 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
+++ b/media/java/android/media/metrics/PlaybackErrorEvent.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,11 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.media.metrics;
-/**
- * Information required to request a Tuner Lnb.
- *
- * @hide
- */
-parcelable TunerLnbRequest;
\ No newline at end of file
+parcelable PlaybackErrorEvent;
diff --git a/media/java/android/media/metrics/PlaybackErrorEvent.java b/media/java/android/media/metrics/PlaybackErrorEvent.java
new file mode 100644
index 0000000..db70005
--- /dev/null
+++ b/media/java/android/media/metrics/PlaybackErrorEvent.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.metrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.util.Objects;
+
+/**
+ * Playback error event.
+ * @hide
+ */
+public final class PlaybackErrorEvent implements Parcelable {
+ public static final int ERROR_CODE_UNKNOWN = 0;
+ public static final int ERROR_CODE_OTHER = 1;
+ public static final int ERROR_CODE_RUNTIME = 2;
+
+ private final @Nullable String mExceptionStack;
+ private final int mErrorCode;
+ private final int mSubErrorCode;
+ private final long mTimeSincePlaybackCreatedMillis;
+
+
+ /** @hide */
+ // TODO: more error types
+ @IntDef(prefix = "ERROR_CODE_", value = {
+ ERROR_CODE_UNKNOWN,
+ ERROR_CODE_OTHER,
+ ERROR_CODE_RUNTIME
+ })
+ @Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ public @interface ErrorCode {}
+
+ /**
+ * Creates a new PlaybackErrorEvent.
+ *
+ * @hide
+ */
+ public PlaybackErrorEvent(
+ @Nullable String exceptionStack,
+ int errorCode,
+ int subErrorCode,
+ long timeSincePlaybackCreatedMillis) {
+ this.mExceptionStack = exceptionStack;
+ this.mErrorCode = errorCode;
+ this.mSubErrorCode = subErrorCode;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ /** @hide */
+ @Nullable
+ public String getExceptionStack() {
+ return mExceptionStack;
+ }
+
+ @ErrorCode
+ public int getErrorCode() {
+ return mErrorCode;
+ }
+
+ public int getSubErrorCode() {
+ return mSubErrorCode;
+ }
+
+ public long getTimeSincePlaybackCreatedMillis() {
+ return mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "PlaybackErrorEvent { "
+ + "exceptionStack = " + mExceptionStack + ", "
+ + "errorCode = " + mErrorCode + ", "
+ + "subErrorCode = " + mSubErrorCode + ", "
+ + "timeSincePlaybackCreatedMillis = " + mTimeSincePlaybackCreatedMillis
+ + " }";
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PlaybackErrorEvent that = (PlaybackErrorEvent) o;
+ return Objects.equals(mExceptionStack, that.mExceptionStack)
+ && mErrorCode == that.mErrorCode
+ && mSubErrorCode == that.mSubErrorCode
+ && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mExceptionStack, mErrorCode, mSubErrorCode,
+ mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ byte flg = 0;
+ if (mExceptionStack != null) flg |= 0x1;
+ dest.writeByte(flg);
+ if (mExceptionStack != null) dest.writeString(mExceptionStack);
+ dest.writeInt(mErrorCode);
+ dest.writeInt(mSubErrorCode);
+ dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ /* package-private */ PlaybackErrorEvent(@NonNull Parcel in) {
+ byte flg = in.readByte();
+ String exceptionStack = (flg & 0x1) == 0 ? null : in.readString();
+ int errorCode = in.readInt();
+ int subErrorCode = in.readInt();
+ long timeSincePlaybackCreatedMillis = in.readLong();
+
+ this.mExceptionStack = exceptionStack;
+ this.mErrorCode = errorCode;
+ this.mSubErrorCode = subErrorCode;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ public static final @NonNull Parcelable.Creator<PlaybackErrorEvent> CREATOR =
+ new Parcelable.Creator<PlaybackErrorEvent>() {
+ @Override
+ public PlaybackErrorEvent[] newArray(int size) {
+ return new PlaybackErrorEvent[size];
+ }
+
+ @Override
+ public PlaybackErrorEvent createFromParcel(@NonNull Parcel in) {
+ return new PlaybackErrorEvent(in);
+ }
+ };
+
+ /**
+ * A builder for {@link PlaybackErrorEvent}
+ */
+ public static final class Builder {
+ private @Nullable Exception mException;
+ private int mErrorCode;
+ private int mSubErrorCode;
+ private long mTimeSincePlaybackCreatedMillis;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @hide
+ */
+ public Builder(
+ @Nullable Exception exception,
+ int errorCode,
+ int subErrorCode,
+ long timeSincePlaybackCreatedMillis) {
+ mException = exception;
+ mErrorCode = errorCode;
+ mSubErrorCode = subErrorCode;
+ mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ /**
+ * Sets the {@link Exception} object.
+ */
+ public @NonNull Builder setException(@NonNull Exception value) {
+ mException = value;
+ return this;
+ }
+
+ /**
+ * Sets error code.
+ */
+ public @NonNull Builder setErrorCode(@ErrorCode int value) {
+ mErrorCode = value;
+ return this;
+ }
+
+ /**
+ * Sets sub error code.
+ */
+ public @NonNull Builder setSubErrorCode(int value) {
+ mSubErrorCode = value;
+ return this;
+ }
+
+ /**
+ * Set the timestamp in milliseconds.
+ */
+ public @NonNull Builder setTimeSincePlaybackCreatedMillis(long value) {
+ mTimeSincePlaybackCreatedMillis = value;
+ return this;
+ }
+
+ /** Builds the instance. */
+ public @NonNull PlaybackErrorEvent build() {
+
+ String stack;
+ if (mException.getStackTrace() != null && mException.getStackTrace().length > 0) {
+ // TODO: a better definition of the stack trace
+ stack = mException.getStackTrace()[0].toString();
+ } else {
+ stack = null;
+ }
+
+ PlaybackErrorEvent o = new PlaybackErrorEvent(
+ stack,
+ mErrorCode,
+ mSubErrorCode,
+ mTimeSincePlaybackCreatedMillis);
+ return o;
+ }
+ }
+}
diff --git a/media/java/android/media/metrics/PlaybackMetrics.java b/media/java/android/media/metrics/PlaybackMetrics.java
index 82a5803..070b4e4 100644
--- a/media/java/android/media/metrics/PlaybackMetrics.java
+++ b/media/java/android/media/metrics/PlaybackMetrics.java
@@ -16,11 +16,19 @@
package android.media.metrics;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.util.AnnotationValidations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.Objects;
/**
@@ -28,38 +36,323 @@
* @hide
*/
public final class PlaybackMetrics implements Parcelable {
- private int mStreamSourceType;
+ // TODO(b/177209128): JavaDoc for the constants.
+ public static final int STREAM_SOURCE_UNKNOWN = 0;
+ public static final int STREAM_SOURCE_NETWORK = 1;
+ public static final int STREAM_SOURCE_DEVICE = 2;
+ public static final int STREAM_SOURCE_MIXED = 3;
+
+ public static final int STREAM_TYPE_UNKNOWN = 0;
+ public static final int STREAM_TYPE_OTHER = 1;
+ public static final int STREAM_TYPE_PROGRESSIVE = 2;
+ public static final int STREAM_TYPE_DASH = 3;
+ public static final int STREAM_TYPE_HLS = 4;
+ public static final int STREAM_TYPE_SS = 5;
+
+ public static final int PLAYBACK_TYPE_VOD = 0;
+ public static final int PLAYBACK_TYPE_LIVE = 1;
+ public static final int PLAYBACK_TYPE_OTHER = 2;
+
+ public static final int DRM_TYPE_NONE = 0;
+ public static final int DRM_TYPE_OTHER = 1;
+ public static final int DRM_TYPE_PLAY_READY = 2;
+ public static final int DRM_TYPE_WIDEVINE_L1 = 3;
+ public static final int DRM_TYPE_WIDEVINE_L3 = 4;
+ // TODO: add DRM_TYPE_CLEARKEY
+
+ public static final int CONTENT_TYPE_MAIN = 0;
+ public static final int CONTENT_TYPE_AD = 1;
+ public static final int CONTENT_TYPE_OTHER = 2;
+
+
+ /** @hide */
+ @IntDef(prefix = "STREAM_SOURCE_", value = {
+ STREAM_SOURCE_UNKNOWN,
+ STREAM_SOURCE_NETWORK,
+ STREAM_SOURCE_DEVICE,
+ STREAM_SOURCE_MIXED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StreamSource {}
+
+ /** @hide */
+ @IntDef(prefix = "STREAM_TYPE_", value = {
+ STREAM_TYPE_UNKNOWN,
+ STREAM_TYPE_OTHER,
+ STREAM_TYPE_PROGRESSIVE,
+ STREAM_TYPE_DASH,
+ STREAM_TYPE_HLS,
+ STREAM_TYPE_SS
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StreamType {}
+
+ /** @hide */
+ @IntDef(prefix = "PLAYBACK_TYPE_", value = {
+ PLAYBACK_TYPE_VOD,
+ PLAYBACK_TYPE_LIVE,
+ PLAYBACK_TYPE_OTHER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PlaybackType {}
+
+ /** @hide */
+ @IntDef(prefix = "DRM_TYPE_", value = {
+ DRM_TYPE_NONE,
+ DRM_TYPE_OTHER,
+ DRM_TYPE_PLAY_READY,
+ DRM_TYPE_WIDEVINE_L1,
+ DRM_TYPE_WIDEVINE_L3
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DrmType {}
+
+ /** @hide */
+ @IntDef(prefix = "CONTENT_TYPE_", value = {
+ CONTENT_TYPE_MAIN,
+ CONTENT_TYPE_AD,
+ CONTENT_TYPE_OTHER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ContentType {}
+
+
+
+ private final long mMediaDurationMillis;
+ private final int mStreamSource;
+ private final int mStreamType;
+ private final int mPlaybackType;
+ private final int mDrmType;
+ private final int mContentType;
+ private final @Nullable String mPlayerName;
+ private final @Nullable String mPlayerVersion;
+ private final @NonNull long[] mExperimentIds;
+ private final int mVideoFramesPlayed;
+ private final int mVideoFramesDropped;
+ private final int mAudioUnderrunCount;
+ private final long mNetworkBytesRead;
+ private final long mLocalBytesRead;
+ private final long mNetworkTransferDurationMillis;
/**
* Creates a new PlaybackMetrics.
*
* @hide
*/
- public PlaybackMetrics(int streamSourceType) {
- this.mStreamSourceType = streamSourceType;
+ public PlaybackMetrics(
+ long mediaDurationMillis,
+ int streamSource,
+ int streamType,
+ int playbackType,
+ int drmType,
+ int contentType,
+ @Nullable String playerName,
+ @Nullable String playerVersion,
+ @NonNull long[] experimentIds,
+ int videoFramesPlayed,
+ int videoFramesDropped,
+ int audioUnderrunCount,
+ long networkBytesRead,
+ long localBytesRead,
+ long networkTransferDurationMillis) {
+ this.mMediaDurationMillis = mediaDurationMillis;
+ this.mStreamSource = streamSource;
+ this.mStreamType = streamType;
+ this.mPlaybackType = playbackType;
+ this.mDrmType = drmType;
+ this.mContentType = contentType;
+ this.mPlayerName = playerName;
+ this.mPlayerVersion = playerVersion;
+ this.mExperimentIds = experimentIds;
+ AnnotationValidations.validate(NonNull.class, null, mExperimentIds);
+ this.mVideoFramesPlayed = videoFramesPlayed;
+ this.mVideoFramesDropped = videoFramesDropped;
+ this.mAudioUnderrunCount = audioUnderrunCount;
+ this.mNetworkBytesRead = networkBytesRead;
+ this.mLocalBytesRead = localBytesRead;
+ this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
}
- public int getStreamSourceType() {
- return mStreamSourceType;
+ public long getMediaDurationMillis() {
+ return mMediaDurationMillis;
+ }
+
+ /**
+ * Gets stream source type.
+ */
+ @StreamSource
+ public int getStreamSource() {
+ return mStreamSource;
+ }
+
+ /**
+ * Gets stream type.
+ */
+ @StreamType
+ public int getStreamType() {
+ return mStreamType;
+ }
+
+
+ /**
+ * Gets playback type.
+ */
+ @PlaybackType
+ public int getPlaybackType() {
+ return mPlaybackType;
+ }
+
+ /**
+ * Gets DRM type.
+ */
+ @DrmType
+ public int getDrmType() {
+ return mDrmType;
+ }
+
+ /**
+ * Gets content type.
+ */
+ @ContentType
+ public int getContentType() {
+ return mContentType;
+ }
+
+ /**
+ * Gets player name.
+ */
+ public @Nullable String getPlayerName() {
+ return mPlayerName;
+ }
+
+ /**
+ * Gets player version.
+ */
+ public @Nullable String getPlayerVersion() {
+ return mPlayerVersion;
+ }
+
+ /**
+ * Gets experiment IDs.
+ */
+ public @NonNull long[] getExperimentIds() {
+ return Arrays.copyOf(mExperimentIds, mExperimentIds.length);
+ }
+
+ /**
+ * Gets video frames played.
+ */
+ public int getVideoFramesPlayed() {
+ return mVideoFramesPlayed;
+ }
+
+ /**
+ * Gets video frames dropped.
+ */
+ public int getVideoFramesDropped() {
+ return mVideoFramesDropped;
+ }
+
+ /**
+ * Gets audio underrun count.
+ */
+ public int getAudioUnderrunCount() {
+ return mAudioUnderrunCount;
+ }
+
+ /**
+ * Gets number of network bytes read.
+ */
+ public long getNetworkBytesRead() {
+ return mNetworkBytesRead;
+ }
+
+ /**
+ * Gets number of local bytes read.
+ */
+ public long getLocalBytesRead() {
+ return mLocalBytesRead;
+ }
+
+ /**
+ * Gets network transfer duration in milliseconds.
+ */
+ public long getNetworkTransferDurationMillis() {
+ return mNetworkTransferDurationMillis;
+ }
+
+ @Override
+ public String toString() {
+ return "PlaybackMetrics { "
+ + "mediaDurationMillis = " + mMediaDurationMillis + ", "
+ + "streamSource = " + mStreamSource + ", "
+ + "streamType = " + mStreamType + ", "
+ + "playbackType = " + mPlaybackType + ", "
+ + "drmType = " + mDrmType + ", "
+ + "contentType = " + mContentType + ", "
+ + "playerName = " + mPlayerName + ", "
+ + "playerVersion = " + mPlayerVersion + ", "
+ + "experimentIds = " + Arrays.toString(mExperimentIds) + ", "
+ + "videoFramesPlayed = " + mVideoFramesPlayed + ", "
+ + "videoFramesDropped = " + mVideoFramesDropped + ", "
+ + "audioUnderrunCount = " + mAudioUnderrunCount + ", "
+ + "networkBytesRead = " + mNetworkBytesRead + ", "
+ + "localBytesRead = " + mLocalBytesRead + ", "
+ + "networkTransferDurationMillis = " + mNetworkTransferDurationMillis
+ + " }";
}
@Override
public boolean equals(@Nullable Object o) {
-
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PlaybackMetrics that = (PlaybackMetrics) o;
- return mStreamSourceType == that.mStreamSourceType;
+ return mMediaDurationMillis == that.mMediaDurationMillis
+ && mStreamSource == that.mStreamSource
+ && mStreamType == that.mStreamType
+ && mPlaybackType == that.mPlaybackType
+ && mDrmType == that.mDrmType
+ && mContentType == that.mContentType
+ && Objects.equals(mPlayerName, that.mPlayerName)
+ && Objects.equals(mPlayerVersion, that.mPlayerVersion)
+ && Arrays.equals(mExperimentIds, that.mExperimentIds)
+ && mVideoFramesPlayed == that.mVideoFramesPlayed
+ && mVideoFramesDropped == that.mVideoFramesDropped
+ && mAudioUnderrunCount == that.mAudioUnderrunCount
+ && mNetworkBytesRead == that.mNetworkBytesRead
+ && mLocalBytesRead == that.mLocalBytesRead
+ && mNetworkTransferDurationMillis == that.mNetworkTransferDurationMillis;
}
@Override
public int hashCode() {
- return Objects.hash(mStreamSourceType);
+ return Objects.hash(mMediaDurationMillis, mStreamSource, mStreamType, mPlaybackType,
+ mDrmType, mContentType, mPlayerName, mPlayerVersion, mExperimentIds,
+ mVideoFramesPlayed, mVideoFramesDropped, mAudioUnderrunCount, mNetworkBytesRead,
+ mLocalBytesRead, mNetworkTransferDurationMillis);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mStreamSourceType);
+ long flg = 0;
+ if (mPlayerName != null) flg |= 0x80;
+ if (mPlayerVersion != null) flg |= 0x100;
+ dest.writeLong(flg);
+ dest.writeLong(mMediaDurationMillis);
+ dest.writeInt(mStreamSource);
+ dest.writeInt(mStreamType);
+ dest.writeInt(mPlaybackType);
+ dest.writeInt(mDrmType);
+ dest.writeInt(mContentType);
+ if (mPlayerName != null) dest.writeString(mPlayerName);
+ if (mPlayerVersion != null) dest.writeString(mPlayerVersion);
+ dest.writeLongArray(mExperimentIds);
+ dest.writeInt(mVideoFramesPlayed);
+ dest.writeInt(mVideoFramesDropped);
+ dest.writeInt(mAudioUnderrunCount);
+ dest.writeLong(mNetworkBytesRead);
+ dest.writeLong(mLocalBytesRead);
+ dest.writeLong(mNetworkTransferDurationMillis);
}
@Override
@@ -69,20 +362,231 @@
/** @hide */
/* package-private */ PlaybackMetrics(@NonNull Parcel in) {
- int streamSourceType = in.readInt();
- this.mStreamSourceType = streamSourceType;
+ long flg = in.readLong();
+ long mediaDurationMillis = in.readLong();
+ int streamSource = in.readInt();
+ int streamType = in.readInt();
+ int playbackType = in.readInt();
+ int drmType = in.readInt();
+ int contentType = in.readInt();
+ String playerName = (flg & 0x80) == 0 ? null : in.readString();
+ String playerVersion = (flg & 0x100) == 0 ? null : in.readString();
+ long[] experimentIds = in.createLongArray();
+ int videoFramesPlayed = in.readInt();
+ int videoFramesDropped = in.readInt();
+ int audioUnderrunCount = in.readInt();
+ long networkBytesRead = in.readLong();
+ long localBytesRead = in.readLong();
+ long networkTransferDurationMillis = in.readLong();
+
+ this.mMediaDurationMillis = mediaDurationMillis;
+ this.mStreamSource = streamSource;
+ this.mStreamType = streamType;
+ this.mPlaybackType = playbackType;
+ this.mDrmType = drmType;
+ this.mContentType = contentType;
+ this.mPlayerName = playerName;
+ this.mPlayerVersion = playerVersion;
+ this.mExperimentIds = experimentIds;
+ AnnotationValidations.validate(NonNull.class, null, mExperimentIds);
+ this.mVideoFramesPlayed = videoFramesPlayed;
+ this.mVideoFramesDropped = videoFramesDropped;
+ this.mAudioUnderrunCount = audioUnderrunCount;
+ this.mNetworkBytesRead = networkBytesRead;
+ this.mLocalBytesRead = localBytesRead;
+ this.mNetworkTransferDurationMillis = networkTransferDurationMillis;
}
public static final @NonNull Parcelable.Creator<PlaybackMetrics> CREATOR =
new Parcelable.Creator<PlaybackMetrics>() {
- @Override
- public PlaybackMetrics[] newArray(int size) {
- return new PlaybackMetrics[size];
- }
+ @Override
+ public PlaybackMetrics[] newArray(int size) {
+ return new PlaybackMetrics[size];
+ }
- @Override
- public PlaybackMetrics createFromParcel(@NonNull Parcel in) {
- return new PlaybackMetrics(in);
- }
- };
+ @Override
+ public PlaybackMetrics createFromParcel(@NonNull Parcel in) {
+ return new PlaybackMetrics(in);
+ }
+ };
+
+ /**
+ * A builder for {@link PlaybackMetrics}
+ */
+ public static final class Builder {
+
+ private long mMediaDurationMillis;
+ private int mStreamSource;
+ private int mStreamType;
+ private int mPlaybackType;
+ private int mDrmType;
+ private int mContentType;
+ private @Nullable String mPlayerName;
+ private @Nullable String mPlayerVersion;
+ private @NonNull List<Long> mExperimentIds = new ArrayList<>();
+ private int mVideoFramesPlayed;
+ private int mVideoFramesDropped;
+ private int mAudioUnderrunCount;
+ private long mNetworkBytesRead;
+ private long mLocalBytesRead;
+ private long mNetworkTransferDurationMillis;
+
+ /**
+ * Creates a new Builder.
+ *
+ * @hide
+ */
+ public Builder() {
+ }
+
+ /**
+ * Sets the media duration in milliseconds.
+ */
+ public @NonNull Builder setMediaDurationMillis(long value) {
+ mMediaDurationMillis = value;
+ return this;
+ }
+
+ /**
+ * Sets the stream source type.
+ */
+ public @NonNull Builder setStreamSource(@StreamSource int value) {
+ mStreamSource = value;
+ return this;
+ }
+
+ /**
+ * Sets the stream type.
+ */
+ public @NonNull Builder setStreamType(@StreamType int value) {
+ mStreamType = value;
+ return this;
+ }
+
+ /**
+ * Sets the playback type.
+ */
+ public @NonNull Builder setPlaybackType(@PlaybackType int value) {
+ mPlaybackType = value;
+ return this;
+ }
+
+ /**
+ * Sets the DRM type.
+ */
+ public @NonNull Builder setDrmType(@StreamType int value) {
+ mDrmType = value;
+ return this;
+ }
+
+ /**
+ * Sets the content type.
+ */
+ public @NonNull Builder setContentType(@ContentType int value) {
+ mContentType = value;
+ return this;
+ }
+
+ /**
+ * Sets the player name.
+ */
+ public @NonNull Builder setPlayerName(@NonNull String value) {
+ mPlayerName = value;
+ return this;
+ }
+
+ /**
+ * Sets the player version.
+ */
+ public @NonNull Builder setPlayerVersion(@NonNull String value) {
+ mPlayerVersion = value;
+ return this;
+ }
+
+ /**
+ * Adds the experiment ID.
+ */
+ public @NonNull Builder addExperimentId(long value) {
+ mExperimentIds.add(value);
+ return this;
+ }
+
+ /**
+ * Sets the video frames played.
+ */
+ public @NonNull Builder setVideoFramesPlayed(int value) {
+ mVideoFramesPlayed = value;
+ return this;
+ }
+
+ /**
+ * Sets the video frames dropped.
+ */
+ public @NonNull Builder setVideoFramesDropped(int value) {
+ mVideoFramesDropped = value;
+ return this;
+ }
+
+ /**
+ * Sets the audio underrun count.
+ */
+ public @NonNull Builder setAudioUnderrunCount(int value) {
+ mAudioUnderrunCount = value;
+ return this;
+ }
+
+ /**
+ * Sets the number of network bytes read.
+ */
+ public @NonNull Builder setNetworkBytesRead(long value) {
+ mNetworkBytesRead = value;
+ return this;
+ }
+
+ /**
+ * Sets the number of local bytes read.
+ */
+ public @NonNull Builder setLocalBytesRead(long value) {
+ mLocalBytesRead = value;
+ return this;
+ }
+
+ /**
+ * Sets the network transfer duration in milliseconds.
+ */
+ public @NonNull Builder setNetworkTransferDurationMillis(long value) {
+ mNetworkTransferDurationMillis = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull PlaybackMetrics build() {
+
+ PlaybackMetrics o = new PlaybackMetrics(
+ mMediaDurationMillis,
+ mStreamSource,
+ mStreamType,
+ mPlaybackType,
+ mDrmType,
+ mContentType,
+ mPlayerName,
+ mPlayerVersion,
+ idsToLongArray(),
+ mVideoFramesPlayed,
+ mVideoFramesDropped,
+ mAudioUnderrunCount,
+ mNetworkBytesRead,
+ mLocalBytesRead,
+ mNetworkTransferDurationMillis);
+ return o;
+ }
+
+ private long[] idsToLongArray() {
+ long[] ids = new long[mExperimentIds.size()];
+ for (int i = 0; i < mExperimentIds.size(); i++) {
+ ids[i] = mExperimentIds.get(i);
+ }
+ return ids;
+ }
+ }
}
diff --git a/media/java/android/media/metrics/PlaybackMetricsManager.java b/media/java/android/media/metrics/PlaybackMetricsManager.java
index d51ff47..63a50ae 100644
--- a/media/java/android/media/metrics/PlaybackMetricsManager.java
+++ b/media/java/android/media/metrics/PlaybackMetricsManager.java
@@ -48,6 +48,29 @@
throw e.rethrowFromSystemServer();
}
}
+ /**
+ * Reports network event.
+ * @hide
+ */
+ public void reportNetworkEvent(@NonNull String sessionId, NetworkEvent event) {
+ try {
+ mService.reportNetworkEvent(sessionId, event, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Reports playback state event.
+ * @hide
+ */
+ public void reportPlaybackStateEvent(@NonNull String sessionId, PlaybackStateEvent event) {
+ try {
+ mService.reportPlaybackStateEvent(sessionId, event, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/**
* Creates a playback session.
@@ -61,4 +84,16 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Reports error event.
+ * @hide
+ */
+ public void reportPlaybackErrorEvent(@NonNull String sessionId, PlaybackErrorEvent event) {
+ try {
+ mService.reportPlaybackErrorEvent(sessionId, event, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/media/java/android/media/metrics/PlaybackSession.java b/media/java/android/media/metrics/PlaybackSession.java
index 4ad8906..061e665 100644
--- a/media/java/android/media/metrics/PlaybackSession.java
+++ b/media/java/android/media/metrics/PlaybackSession.java
@@ -50,6 +50,27 @@
mManager.reportPlaybackMetrics(mId, metrics);
}
+ /**
+ * Reports error event.
+ */
+ public void reportPlaybackErrorEvent(PlaybackErrorEvent event) {
+ mManager.reportPlaybackErrorEvent(mId, event);
+ }
+
+ /**
+ * Reports network event.
+ */
+ public void reportNetworkEvent(NetworkEvent event) {
+ mManager.reportNetworkEvent(mId, event);
+ }
+
+ /**
+ * Reports playback state event.
+ */
+ public void reportPlaybackStateEvent(PlaybackStateEvent event) {
+ mManager.reportPlaybackStateEvent(mId, event);
+ }
+
public @NonNull String getId() {
return mId;
}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl b/media/java/android/media/metrics/PlaybackStateEvent.aidl
similarity index 74%
copy from media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
copy to media/java/android/media/metrics/PlaybackStateEvent.aidl
index 0e6fcde..8b8d05b 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
+++ b/media/java/android/media/metrics/PlaybackStateEvent.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,11 +14,6 @@
* limitations under the License.
*/
-package android.media.tv.tunerresourcemanager;
+package android.media.metrics;
-/**
- * Information required to request a Tuner Lnb.
- *
- * @hide
- */
-parcelable TunerLnbRequest;
\ No newline at end of file
+parcelable PlaybackStateEvent;
diff --git a/media/java/android/media/metrics/PlaybackStateEvent.java b/media/java/android/media/metrics/PlaybackStateEvent.java
new file mode 100644
index 0000000..6ce5bf0
--- /dev/null
+++ b/media/java/android/media/metrics/PlaybackStateEvent.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.metrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.util.Objects;
+
+/**
+ * Playback state event.
+ * @hide
+ */
+public final class PlaybackStateEvent implements Parcelable {
+ // TODO: more states
+ /** Playback has not started (initial state) */
+ public static final int STATE_NOT_STARTED = 0;
+ /** Playback is buffering in the background for initial playback start */
+ public static final int STATE_JOINING_BACKGROUND = 1;
+ /** Playback is buffering in the foreground for initial playback start */
+ public static final int STATE_JOINING_FOREGROUND = 2;
+ /** Playback is actively playing */
+ public static final int STATE_PLAYING = 3;
+ /** Playback is paused but ready to play */
+ public static final int STATE_PAUSED = 4;
+
+ private int mState;
+ private long mTimeSincePlaybackCreatedMillis;
+
+ // These track ExoPlayer states. See the ExoPlayer documentation for the state transitions.
+ @IntDef(prefix = "STATE_", value = {
+ STATE_NOT_STARTED,
+ STATE_JOINING_BACKGROUND,
+ STATE_JOINING_FOREGROUND,
+ STATE_PLAYING,
+ STATE_PAUSED
+ })
+ @Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+ public @interface State {}
+
+ /**
+ * Converts playback state to string.
+ */
+ public static String stateToString(@State int value) {
+ switch (value) {
+ case STATE_NOT_STARTED:
+ return "STATE_NOT_STARTED";
+ case STATE_JOINING_BACKGROUND:
+ return "STATE_JOINING_BACKGROUND";
+ case STATE_JOINING_FOREGROUND:
+ return "STATE_JOINING_FOREGROUND";
+ case STATE_PLAYING:
+ return "STATE_PLAYING";
+ case STATE_PAUSED:
+ return "STATE_PAUSED";
+ default:
+ return Integer.toHexString(value);
+ }
+ }
+
+ /**
+ * Creates a new PlaybackStateEvent.
+ *
+ * @hide
+ */
+ public PlaybackStateEvent(
+ int state,
+ long timeSincePlaybackCreatedMillis) {
+ this.mState = state;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ /**
+ * Gets playback state.
+ * @return
+ */
+ public int getState() {
+ return mState;
+ }
+
+ /**
+ * Gets time since the corresponding playback is created in millisecond.
+ */
+ public long getTimeSincePlaybackCreatedMillis() {
+ return mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PlaybackStateEvent that = (PlaybackStateEvent) o;
+ return mState == that.mState
+ && mTimeSincePlaybackCreatedMillis == that.mTimeSincePlaybackCreatedMillis;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mState, mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mState);
+ dest.writeLong(mTimeSincePlaybackCreatedMillis);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** @hide */
+ /* package-private */ PlaybackStateEvent(@NonNull Parcel in) {
+ int state = in.readInt();
+ long timeSincePlaybackCreatedMillis = in.readLong();
+
+ this.mState = state;
+ this.mTimeSincePlaybackCreatedMillis = timeSincePlaybackCreatedMillis;
+ }
+
+ public static final @NonNull Parcelable.Creator<PlaybackStateEvent> CREATOR =
+ new Parcelable.Creator<PlaybackStateEvent>() {
+ @Override
+ public PlaybackStateEvent[] newArray(int size) {
+ return new PlaybackStateEvent[size];
+ }
+
+ @Override
+ public PlaybackStateEvent createFromParcel(@NonNull Parcel in) {
+ return new PlaybackStateEvent(in);
+ }
+ };
+
+}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 1fd132d..f580ea5 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -140,6 +140,8 @@
@NonNull
public ISession createSession(@NonNull MediaSession.CallbackStub cbStub, @NonNull String tag,
@Nullable Bundle sessionInfo) {
+ Objects.requireNonNull(cbStub, "cbStub shouldn't be null");
+ Objects.requireNonNull(tag, "tag shouldn't be null");
try {
return mService.createSession(mContext.getPackageName(), cbStub, tag, sessionInfo,
UserHandle.myUserId());
@@ -163,9 +165,7 @@
* @param token newly created session2 token
*/
public void notifySession2Created(@NonNull Session2Token token) {
- if (token == null) {
- throw new IllegalArgumentException("token shouldn't be null");
- }
+ Objects.requireNonNull(token, "token shouldn't be null");
if (token.getType() != Session2Token.TYPE_SESSION) {
throw new IllegalArgumentException("token's type should be TYPE_SESSION");
}
@@ -209,16 +209,24 @@
* retrieve sessions for user ids that do not belong to current process.
*
* @param notificationListener The enabled notification listener component. May be null.
- * @param userId The user id to fetch sessions for.
+ * @param userHandle The user handle to fetch sessions for.
* @return A list of controllers for ongoing sessions.
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("UserHandle")
public @NonNull List<MediaController> getActiveSessionsForUser(
- @Nullable ComponentName notificationListener, int userId) {
+ @Nullable ComponentName notificationListener, @NonNull UserHandle userHandle) {
+ Objects.requireNonNull(userHandle, "userHandle shouldn't be null");
+ return getActiveSessionsForUser(notificationListener, userHandle.getIdentifier());
+ }
+
+ private List<MediaController> getActiveSessionsForUser(ComponentName notificationListener,
+ int userId) {
ArrayList<MediaController> controllers = new ArrayList<MediaController>();
try {
- List<MediaSession.Token> tokens = mService.getSessions(notificationListener, userId);
+ List<MediaSession.Token> tokens = mService.getSessions(notificationListener,
+ userId);
int size = tokens.size();
for (int i = 0; i < size; i++) {
MediaController controller = new MediaController(mContext, tokens.get(i));
@@ -257,12 +265,19 @@
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
* retrieve session tokens for user ids that do not belong to current process.
*
- * @param userId The user id to fetch sessions for.
+ * @param userHandle The user handle to fetch sessions for.
* @return A list of {@link Session2Token}
* @hide
*/
@NonNull
- public List<Session2Token> getSession2Tokens(int userId) {
+ @SuppressLint("UserHandle")
+ public List<Session2Token> getSession2Tokens(@NonNull UserHandle userHandle) {
+ Objects.requireNonNull(userHandle, "userHandle shouldn't be null");
+ return getSession2Tokens(userHandle.getIdentifier());
+
+ }
+
+ private List<Session2Token> getSession2Tokens(int userId) {
try {
ParceledListSlice slice = mService.getSession2Tokens(userId);
return slice == null ? new ArrayList<>() : slice.getList();
@@ -324,18 +339,26 @@
*
* @param sessionListener The listener to add.
* @param notificationListener The enabled notification listener component. May be null.
- * @param userId The userId to listen for changes on.
+ * @param userHandle The user handle to listen for changes on.
* @param handler The handler to post updates on.
* @hide
*/
- @SuppressLint({"ExecutorRegistration", "SamShouldBeLast"})
+ @SuppressLint({"ExecutorRegistration", "SamShouldBeLast", "UserHandle"})
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void addOnActiveSessionsChangedListener(
@NonNull OnActiveSessionsChangedListener sessionListener,
- @Nullable ComponentName notificationListener, int userId, @Nullable Handler handler) {
- if (sessionListener == null) {
- throw new IllegalArgumentException("listener may not be null");
- }
+ @Nullable ComponentName notificationListener, @NonNull UserHandle userHandle,
+ @Nullable Handler handler) {
+ Objects.requireNonNull(userHandle, "userHandle shouldn't be null");
+ addOnActiveSessionsChangedListener(sessionListener, notificationListener,
+ userHandle.getIdentifier(), handler);
+ }
+
+ private void addOnActiveSessionsChangedListener(
+ @NonNull OnActiveSessionsChangedListener sessionListener,
+ @Nullable ComponentName notificationListener, int userId,
+ @Nullable Handler handler) {
+ Objects.requireNonNull(sessionListener, "sessionListener shouldn't be null");
if (handler == null) {
handler = new Handler();
}
@@ -358,15 +381,13 @@
/**
* Stop receiving active sessions updates on the specified listener.
*
- * @param listener The listener to remove.
+ * @param sessionListener The listener to remove.
*/
public void removeOnActiveSessionsChangedListener(
- @NonNull OnActiveSessionsChangedListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener may not be null");
- }
+ @NonNull OnActiveSessionsChangedListener sessionListener) {
+ Objects.requireNonNull(sessionListener, "sessionListener shouldn't be null");
synchronized (mLock) {
- SessionsChangedWrapper wrapper = mListeners.remove(listener);
+ SessionsChangedWrapper wrapper = mListeners.remove(sessionListener);
if (wrapper != null) {
try {
mService.removeSessionsListener(wrapper.mStub);
@@ -422,17 +443,23 @@
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
* add listeners for user ids that do not belong to current process.
*
- * @param userId The userId to listen for changes on
+ * @param userHandle The userHandle to listen for changes on
* @param listener The listener to add
* @param handler The handler to call listener on. If {@code null}, calling thread's looper will
* be used.
* @hide
*/
- public void addOnSession2TokensChangedListener(int userId,
- @NonNull OnSession2TokensChangedListener listener, @Nullable Handler handler) {
- if (listener == null) {
- throw new IllegalArgumentException("listener shouldn't be null");
- }
+ @SuppressLint("UserHandle")
+ public void addOnSession2TokensChangedListener(@NonNull UserHandle userHandle,
+ @NonNull OnSession2TokensChangedListener listener, @NonNull Handler handler) {
+ Objects.requireNonNull(userHandle, "userHandle shouldn't be null");
+ addOnSession2TokensChangedListener(userHandle.getIdentifier(), listener, handler);
+ }
+
+ private void addOnSession2TokensChangedListener(int userId,
+ OnSession2TokensChangedListener listener, Handler handler) {
+ Objects.requireNonNull(handler, "handler shouldn't be null");
+ Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
if (mSession2TokensListeners.get(listener) != null) {
Log.w(TAG, "Attempted to add session listener twice, ignoring.");
@@ -462,9 +489,7 @@
*/
public void removeOnSession2TokensChangedListener(
@NonNull OnSession2TokensChangedListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener may not be null");
- }
+ Objects.requireNonNull(listener, "listener shouldn't be null");
final Session2TokensChangedWrapper wrapper;
synchronized (mLock) {
wrapper = mSession2TokensListeners.remove(listener);
@@ -581,9 +606,7 @@
private void dispatchMediaKeyEventInternal(KeyEvent keyEvent, boolean asSystemService,
boolean needWakeLock) {
- if (keyEvent == null) {
- throw new NullPointerException("keyEvent shouldn't be null");
- }
+ Objects.requireNonNull(keyEvent, "keyEvent shouldn't be null");
try {
mService.dispatchMediaKeyEvent(mContext.getPackageName(), asSystemService, keyEvent,
needWakeLock);
@@ -606,12 +629,8 @@
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public boolean dispatchMediaKeyEventToSessionAsSystemService(@NonNull KeyEvent keyEvent,
@NonNull MediaSession.Token sessionToken) {
- if (sessionToken == null) {
- throw new NullPointerException("sessionToken shouldn't be null");
- }
- if (keyEvent == null) {
- throw new NullPointerException("keyEvent shouldn't be null");
- }
+ Objects.requireNonNull(sessionToken, "sessionToken shouldn't be null");
+ Objects.requireNonNull(keyEvent, "keyEvent shouldn't be null");
if (!KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
return false;
}
@@ -662,9 +681,7 @@
private void dispatchVolumeKeyEventInternal(@NonNull KeyEvent keyEvent, int stream,
boolean musicOnly, boolean asSystemService) {
- if (keyEvent == null) {
- throw new NullPointerException("keyEvent shouldn't be null");
- }
+ Objects.requireNonNull(keyEvent, "keyEvent shouldn't be null");
try {
mService.dispatchVolumeKeyEvent(mContext.getPackageName(), mContext.getOpPackageName(),
asSystemService, keyEvent, stream, musicOnly);
@@ -686,12 +703,8 @@
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void dispatchVolumeKeyEventToSessionAsSystemService(@NonNull KeyEvent keyEvent,
@NonNull MediaSession.Token sessionToken) {
- if (sessionToken == null) {
- throw new NullPointerException("sessionToken shouldn't be null");
- }
- if (keyEvent == null) {
- throw new NullPointerException("keyEvent shouldn't be null");
- }
+ Objects.requireNonNull(sessionToken, "sessionToken shouldn't be null");
+ Objects.requireNonNull(keyEvent, "keyEvent shouldn't be null");
try {
mService.dispatchVolumeKeyEventToSessionAsSystemService(mContext.getPackageName(),
mContext.getOpPackageName(), keyEvent, sessionToken);
@@ -735,9 +748,7 @@
* {@code false} otherwise.
*/
public boolean isTrustedForMediaControl(@NonNull RemoteUserInfo userInfo) {
- if (userInfo == null) {
- throw new IllegalArgumentException("userInfo may not be null");
- }
+ Objects.requireNonNull(userInfo, "userInfo shouldn't be null");
if (userInfo.getPackageName() == null) {
return false;
}
@@ -845,12 +856,8 @@
public void addOnMediaKeyEventDispatchedListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull OnMediaKeyEventDispatchedListener listener) {
- if (executor == null) {
- throw new NullPointerException("executor shouldn't be null");
- }
- if (listener == null) {
- throw new NullPointerException("listener shouldn't be null");
- }
+ Objects.requireNonNull(executor, "executor shouldn't be null");
+ Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
try {
mOnMediaKeyEventDispatchedListeners.put(listener, executor);
@@ -874,9 +881,7 @@
@RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
public void removeOnMediaKeyEventDispatchedListener(
@NonNull OnMediaKeyEventDispatchedListener listener) {
- if (listener == null) {
- throw new NullPointerException("listener shouldn't be null");
- }
+ Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
try {
mOnMediaKeyEventDispatchedListeners.remove(listener);
@@ -902,12 +907,8 @@
public void addOnMediaKeyEventSessionChangedListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull OnMediaKeyEventSessionChangedListener listener) {
- if (executor == null) {
- throw new NullPointerException("executor shouldn't be null");
- }
- if (listener == null) {
- throw new NullPointerException("listener shouldn't be null");
- }
+ Objects.requireNonNull(executor, "executor shouldn't be null");
+ Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
try {
mMediaKeyEventSessionChangedCallbacks.put(listener, executor);
@@ -934,9 +935,7 @@
@RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
public void removeOnMediaKeyEventSessionChangedListener(
@NonNull OnMediaKeyEventSessionChangedListener listener) {
- if (listener == null) {
- throw new NullPointerException("listener shouldn't be null");
- }
+ Objects.requireNonNull(listener, "listener shouldn't be null");
synchronized (mLock) {
try {
mMediaKeyEventSessionChangedCallbacks.remove(listener);
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index ed99fad..d8d1ba13 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -94,6 +94,8 @@
// For the recording session
void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId);
void stopRecording(in IBinder sessionToken, int userId);
+ void pauseRecording(in IBinder sessionToken, in Bundle params, int userId);
+ void resumeRecording(in IBinder sessionToken, in Bundle params, int userId);
// For TV input hardware binding
List<TvInputHardwareInfo> getHardwareList();
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 24b87d5..158cf21 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -58,4 +58,6 @@
// For the recording session
void startRecording(in Uri programUri, in Bundle params);
void stopRecording();
+ void pauseRecording(in Bundle params);
+ void resumeRecording(in Bundle params);
}
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index e89d33d..abccf8d 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -68,6 +68,8 @@
private static final int DO_TIME_SHIFT_ENABLE_POSITION_TRACKING = 19;
private static final int DO_START_RECORDING = 20;
private static final int DO_STOP_RECORDING = 21;
+ private static final int DO_PAUSE_RECORDING = 22;
+ private static final int DO_RESUME_RECORDING = 23;
private final boolean mIsRecordingSession;
private final HandlerCaller mCaller;
@@ -224,6 +226,14 @@
mTvInputRecordingSessionImpl.stopRecording();
break;
}
+ case DO_PAUSE_RECORDING: {
+ mTvInputRecordingSessionImpl.pauseRecording((Bundle) msg.obj);
+ break;
+ }
+ case DO_RESUME_RECORDING: {
+ mTvInputRecordingSessionImpl.resumeRecording((Bundle) msg.obj);
+ break;
+ }
default: {
Log.w(TAG, "Unhandled message code: " + msg.what);
break;
@@ -363,6 +373,16 @@
mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_STOP_RECORDING));
}
+ @Override
+ public void pauseRecording(@Nullable Bundle params) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_PAUSE_RECORDING, params));
+ }
+
+ @Override
+ public void resumeRecording(@Nullable Bundle params) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RESUME_RECORDING, params));
+ }
+
private final class TvInputEventReceiver extends InputEventReceiver {
public TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
diff --git a/media/java/android/media/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java
index b12f7c5..1249e0d 100644
--- a/media/java/android/media/tv/TvInputHardwareInfo.java
+++ b/media/java/android/media/tv/TvInputHardwareInfo.java
@@ -188,6 +188,17 @@
mCableConnectionStatus = source.readInt();
}
+ /** @hide */
+ public Builder toBuilder() {
+ return new Builder()
+ .deviceId(mDeviceId)
+ .type(mType)
+ .audioType(mAudioType)
+ .audioAddress(mAudioAddress)
+ .hdmiPortId(mHdmiPortId)
+ .cableConnectionStatus(mCableConnectionStatus);
+ }
+
public static final class Builder {
private Integer mDeviceId = null;
private Integer mType = null;
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 195ad5b..54cb2bf 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -143,6 +143,7 @@
// Attributes from XML meta data.
private final String mSetupActivity;
private final boolean mCanRecord;
+ private final boolean mCanPauseRecording;
private final int mTunerCount;
// Attributes specific to HDMI
@@ -264,8 +265,8 @@
private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
- String setupActivity, boolean canRecord, int tunerCount, HdmiDeviceInfo hdmiDeviceInfo,
- boolean isConnectedToHdmiSwitch,
+ String setupActivity, boolean canRecord, boolean canPauseRecording, int tunerCount,
+ HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch,
@HdmiAddressRelativePosition int hdmiConnectionRelativePosition, String parentId,
Bundle extras) {
mService = service;
@@ -279,6 +280,7 @@
mIconDisconnected = iconDisconnected;
mSetupActivity = setupActivity;
mCanRecord = canRecord;
+ mCanPauseRecording = canPauseRecording;
mTunerCount = tunerCount;
mHdmiDeviceInfo = hdmiDeviceInfo;
mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
@@ -386,6 +388,14 @@
}
/**
+ * Returns {@code true} if this TV input can pause recording TV programs,
+ * {@code false} otherwise.
+ */
+ public boolean canPauseRecording() {
+ return mCanPauseRecording;
+ }
+
+ /**
* Returns domain-specific extras associated with this TV input.
*/
public Bundle getExtras() {
@@ -571,6 +581,7 @@
&& Objects.equals(mIconDisconnected, obj.mIconDisconnected)
&& TextUtils.equals(mSetupActivity, obj.mSetupActivity)
&& mCanRecord == obj.mCanRecord
+ && mCanPauseRecording == obj.mCanPauseRecording
&& mTunerCount == obj.mTunerCount
&& Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
&& mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch
@@ -606,6 +617,7 @@
dest.writeParcelable(mIconDisconnected, flags);
dest.writeString(mSetupActivity);
dest.writeByte(mCanRecord ? (byte) 1 : 0);
+ dest.writeByte(mCanPauseRecording ? (byte) 1 : 0);
dest.writeInt(mTunerCount);
dest.writeParcelable(mHdmiDeviceInfo, flags);
dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
@@ -648,6 +660,7 @@
mIconDisconnected = in.readParcelable(null);
mSetupActivity = in.readString();
mCanRecord = in.readByte() == 1;
+ mCanPauseRecording = in.readByte() == 1;
mTunerCount = in.readInt();
mHdmiDeviceInfo = in.readParcelable(null);
mIsConnectedToHdmiSwitch = in.readByte() == 1;
@@ -695,6 +708,7 @@
private Icon mIconDisconnected;
private String mSetupActivity;
private Boolean mCanRecord;
+ private Boolean mCanPauseRecording;
private Integer mTunerCount;
private TvInputHardwareInfo mTvInputHardwareInfo;
private HdmiDeviceInfo mHdmiDeviceInfo;
@@ -879,6 +893,18 @@
}
/**
+ * Sets whether this TV input can pause recording TV programs or not.
+ *
+ * @param canPauseRecording Whether this TV input can pause recording TV programs.
+ * @return This Builder object to allow for chaining of calls to builder methods.
+ */
+ @NonNull
+ public Builder setCanPauseRecording(boolean canPauseRecording) {
+ this.mCanPauseRecording = canPauseRecording;
+ return this;
+ }
+
+ /**
* Sets domain-specific extras associated with this TV input.
*
* @param extras Domain-specific extras associated with this TV input. Keys <em>must</em> be
@@ -927,7 +953,9 @@
parseServiceMetadata(type);
return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId,
mIcon, mIconStandby, mIconDisconnected, mSetupActivity,
- mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
+ mCanRecord == null ? false : mCanRecord,
+ mCanPauseRecording == null ? false : mCanPauseRecording,
+ mTunerCount == null ? 0 : mTunerCount,
mHdmiDeviceInfo, isConnectedToHdmiSwitch, hdmiConnectionRelativePosition,
mParentId, mExtras);
}
@@ -997,6 +1025,12 @@
mTunerCount = sa.getInt(
com.android.internal.R.styleable.TvInputService_tunerCount, 1);
}
+ if (mCanPauseRecording == null) {
+ mCanPauseRecording = sa.getBoolean(
+ com.android.internal.R.styleable.TvInputService_canPauseRecording,
+ false);
+ }
+
sa.recycle();
} catch (IOException | XmlPullParserException e) {
throw new IllegalStateException("Failed reading meta-data for " + si.packageName, e);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index e9959be..98b9ad8 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -2523,6 +2523,40 @@
}
/**
+ * Pauses TV program recording in the current recording session.
+ *
+ * @param params A set of extra parameters which might be handled with this event.
+ */
+ void pauseRecording(@NonNull Bundle params) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.pauseRecording(mToken, params, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Resumes TV program recording in the current recording session.
+ *
+ * @param params A set of extra parameters which might be handled with this event.
+ */
+ void resumeRecording(@NonNull Bundle params) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.resumeRecording(mToken, params, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle)
* TvInputService.Session.appPrivateCommand()} on the current TvView.
*
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 945fb3b..77fb2b2 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -1873,6 +1873,28 @@
/**
+ * Called when the application requests to pause TV program recording. Recording must pause
+ * immediately when this method is called.
+ *
+ * If the pause request cannot be fulfilled, the session must call
+ * {@link #notifyError(int)}.
+ *
+ * @param params Domain-specific data for recording request.
+ */
+ public void onPauseRecording(@NonNull Bundle params) { }
+
+ /**
+ * Called when the application requests to resume TV program recording. Recording must
+ * resume immediately when this method is called.
+ *
+ * If the resume request cannot be fulfilled, the session must call
+ * {@link #notifyError(int)}.
+ *
+ * @param params Domain-specific data for recording request.
+ */
+ public void onResumeRecording(@NonNull Bundle params) { }
+
+ /**
* Called when the application requests to release all the resources held by this recording
* session.
*/
@@ -1924,6 +1946,22 @@
}
/**
+ * Calls {@link #onPauseRecording(Bundle)}.
+ *
+ */
+ void pauseRecording(@NonNull Bundle params) {
+ onPauseRecording(params);
+ }
+
+ /**
+ * Calls {@link #onResumeRecording(Bundle)}.
+ *
+ */
+ void resumeRecording(@NonNull Bundle params) {
+ onResumeRecording(params);
+ }
+
+ /**
* Calls {@link #onAppPrivateCommand(String, Bundle)}.
*/
void appPrivateCommand(String action, Bundle data) {
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 23fadac..180e2bd 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -30,6 +30,7 @@
import android.util.Pair;
import java.util.ArrayDeque;
+import java.util.Objects;
import java.util.Queue;
/**
@@ -49,6 +50,8 @@
private boolean mIsRecordingStarted;
private boolean mIsTuned;
+ private boolean mIsPaused;
+ private boolean mIsRecordingStopping;
private final Queue<Pair<String, Bundle>> mPendingAppPrivateCommands = new ArrayDeque<>();
/**
@@ -113,17 +116,22 @@
if (TextUtils.isEmpty(inputId)) {
throw new IllegalArgumentException("inputId cannot be null or an empty string");
}
- if (mIsRecordingStarted) {
+ if (mIsRecordingStarted && !mIsPaused) {
throw new IllegalStateException("tune failed - recording already started");
}
if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) {
if (mSession != null) {
+ mSessionCallback.mChannelUri = channelUri;
mSession.tune(channelUri, params);
} else {
mSessionCallback.mChannelUri = channelUri;
mSessionCallback.mConnectionParams = params;
}
+ mIsTuned = false;
} else {
+ if (mIsPaused) {
+ throw new IllegalStateException("tune failed - inputId is changed during pause");
+ }
resetInternal();
mSessionCallback = new MySessionCallback(inputId, channelUri, params);
if (mTvInputManager != null) {
@@ -148,6 +156,8 @@
mSession.release();
mIsTuned = false;
mIsRecordingStarted = false;
+ mIsPaused = false;
+ mIsRecordingStopping = false;
mSession = null;
}
}
@@ -169,7 +179,8 @@
*
* @param programUri The URI for the TV program to record, built by
* {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
- * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
+ * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during
+ * pause.
*/
public void startRecording(@Nullable Uri programUri) {
startRecording(programUri, Bundle.EMPTY);
@@ -195,11 +206,16 @@
* @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
* name, i.e. prefixed with a package name you own, so that different developers will
* not create conflicting keys.
- * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
+ * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during
+ * pause.
*/
public void startRecording(@Nullable Uri programUri, @NonNull Bundle params) {
- if (!mIsTuned) {
- throw new IllegalStateException("startRecording failed - not yet tuned");
+ if (mIsRecordingStopping || !mIsTuned || mIsPaused) {
+ throw new IllegalStateException("startRecording failed -"
+ + "recording not yet stopped or not yet tuned or paused");
+ }
+ if (mIsRecordingStarted) {
+ Log.w(TAG, "startRecording failed - recording already started");
}
if (mSession != null) {
mSession.startRecording(programUri, params);
@@ -225,6 +241,103 @@
}
if (mSession != null) {
mSession.stopRecording();
+ if (mIsRecordingStarted) {
+ mIsRecordingStopping = true;
+ }
+ }
+ }
+
+ /**
+ * Pause TV program recording in the current recording session. Recording is expected to pause
+ * immediately when this method is called. If recording has not yet started in the current
+ * recording session, this method does nothing.
+ *
+ * <p>In pause status, the application can tune during recording. To continue recording,
+ * please call {@link TvRecordingClient#resumeRecording()} to resume instead of
+ * {@link TvRecordingClient#startRecording(Uri)}. Application can stop
+ * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status.
+ *
+ * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+ * {@link RecordingCallback#onError(int)}.
+ */
+ public void pauseRecording() {
+ pauseRecording(Bundle.EMPTY);
+ }
+
+ /**
+ * Pause TV program recording in the current recording session. Recording is expected to pause
+ * immediately when this method is called. If recording has not yet started in the current
+ * recording session, this method does nothing.
+ *
+ * <p>In pause status, the application can tune during recording. To continue recording,
+ * please call {@link TvRecordingClient#resumeRecording()} to resume instead of
+ * {@link TvRecordingClient#startRecording(Uri)}. Application can stop
+ * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status.
+ *
+ * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+ * {@link RecordingCallback#onError(int)}.
+ *
+ * @param params Domain-specific data for this request.
+ */
+ public void pauseRecording(@NonNull Bundle params) {
+ if (!mIsRecordingStarted || mIsRecordingStopping) {
+ throw new IllegalStateException(
+ "pauseRecording failed - recording not yet started or stopping");
+ }
+ TvInputInfo info = mTvInputManager.getTvInputInfo(mSessionCallback.mInputId);
+ if (info == null || !info.canPauseRecording()) {
+ throw new UnsupportedOperationException(
+ "pauseRecording failed - operation not supported");
+ }
+ if (mIsPaused) {
+ Log.w(TAG, "pauseRecording failed - recording already paused");
+ }
+ if (mSession != null) {
+ mSession.pauseRecording(params);
+ mIsPaused = true;
+ }
+ }
+
+ /**
+ * Resume TV program recording only in recording pause status in the current recording session.
+ * Recording is expected to resume immediately when this method is called. If recording has not
+ * yet paused in the current recording session, this method does nothing.
+ *
+ * <p>When record is resumed, the recording is continue and can not re-tune. Application can
+ * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed.
+ *
+ * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+ * {@link RecordingCallback#onError(int)}.
+ */
+ public void resumeRecording() {
+ resumeRecording(Bundle.EMPTY);
+ }
+
+ /**
+ * Resume TV program recording only in recording pause status in the current recording session.
+ * Recording is expected to resume immediately when this method is called. If recording has not
+ * yet paused in the current recording session, this method does nothing.
+ *
+ * <p>When record is resumed, the recording is continues and can not re-tune. Application can
+ * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed.
+ *
+ * <p>If the resume request cannot be fulfilled, the recording session will respond by calling
+ * {@link RecordingCallback#onError(int)}.
+ *
+ * @param params Domain-specific data for this request.
+ */
+ public void resumeRecording(@NonNull Bundle params) {
+ if (!mIsRecordingStarted || mIsRecordingStopping || !mIsTuned) {
+ throw new IllegalStateException(
+ "resumeRecording failed - recording not yet started or stopping or "
+ + "not yet tuned");
+ }
+ if (!mIsPaused) {
+ Log.w(TAG, "resumeRecording failed - recording not yet paused");
+ }
+ if (mSession != null) {
+ mSession.resumeRecording(params);
+ mIsPaused = false;
}
}
@@ -367,6 +480,10 @@
Log.w(TAG, "onTuned - session not created");
return;
}
+ if (mIsTuned || !Objects.equals(mChannelUri, channelUri)) {
+ Log.w(TAG, "onTuned - already tuned or not yet tuned to last channel");
+ return;
+ }
mIsTuned = true;
mCallback.onTuned(channelUri);
}
@@ -382,6 +499,8 @@
}
mIsTuned = false;
mIsRecordingStarted = false;
+ mIsPaused = false;
+ mIsRecordingStopping = false;
mSessionCallback = null;
mSession = null;
if (mCallback != null) {
@@ -398,7 +517,13 @@
Log.w(TAG, "onRecordingStopped - session not created");
return;
}
+ if (!mIsRecordingStarted) {
+ Log.w(TAG, "onRecordingStopped - recording not yet started");
+ return;
+ }
mIsRecordingStarted = false;
+ mIsPaused = false;
+ mIsRecordingStopping = false;
mCallback.onRecordingStopped(recordedProgramUri);
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 9abd8fc..7192c07 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -44,9 +44,9 @@
import android.media.tv.tuner.frontend.OnTuneEventListener;
import android.media.tv.tuner.frontend.ScanCallback;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
-import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
@@ -298,6 +298,8 @@
private Executor mOnResourceLostListenerExecutor;
private Integer mDemuxHandle;
+ private Integer mFrontendCiCamHandle;
+ private Integer mFrontendCiCamId;
private Map<Integer, WeakReference<Descrambler>> mDescramblers = new HashMap<>();
private List<WeakReference<Filter>> mFilters = new ArrayList<WeakReference<Filter>>();
@@ -343,33 +345,14 @@
mHandler = createEventHandler();
int[] clientId = new int[1];
- ResourceClientProfile profile = new ResourceClientProfile(tvInputSessionId, useCase);
+ ResourceClientProfile profile = new ResourceClientProfile();
+ profile.tvInputSessionId = tvInputSessionId;
+ profile.useCase = useCase;
mTunerResourceManager.registerClientProfile(
profile, new HandlerExecutor(mHandler), mResourceListener, clientId);
mClientId = clientId[0];
mUserId = ActivityManager.getCurrentUser();
-
- setFrontendInfoList();
- }
-
- private void setFrontendInfoList() {
- List<Integer> ids = getFrontendIds();
- if (ids == null) {
- return;
- }
- TunerFrontendInfo[] infos = new TunerFrontendInfo[ids.size()];
- for (int i = 0; i < ids.size(); i++) {
- int id = ids.get(i);
- FrontendInfo frontendInfo = getFrontendInfoById(id);
- if (frontendInfo == null) {
- continue;
- }
- TunerFrontendInfo tunerFrontendInfo = new TunerFrontendInfo(
- id, frontendInfo.getType(), frontendInfo.getExclusiveGroupId());
- infos[i] = tunerFrontendInfo;
- }
- mTunerResourceManager.setFrontendInfoList(infos);
}
/**
@@ -489,6 +472,14 @@
if (mLnb != null) {
mLnb.close();
}
+ if (mFrontendCiCamHandle != null) {
+ int result = nativeUnlinkCiCam(mFrontendCiCamId);
+ if (result == RESULT_SUCCESS) {
+ mTunerResourceManager.releaseCiCam(mFrontendCiCamHandle, mClientId);
+ mFrontendCiCamId = null;
+ mFrontendCiCamHandle = null;
+ }
+ }
synchronized (mDescramblers) {
if (!mDescramblers.isEmpty()) {
for (Map.Entry<Integer, WeakReference<Descrambler>> d : mDescramblers.entrySet()) {
@@ -804,7 +795,9 @@
private boolean requestFrontend() {
int[] feHandle = new int[1];
- TunerFrontendRequest request = new TunerFrontendRequest(mClientId, mFrontendType);
+ TunerFrontendRequest request = new TunerFrontendRequest();
+ request.clientId = mClientId;
+ request.frontendType = mFrontendType;
boolean granted = mTunerResourceManager.requestFrontend(request, feHandle);
if (granted) {
mFrontendHandle = feHandle[0];
@@ -935,7 +928,8 @@
public int connectFrontendToCiCam(int ciCamId) {
if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
"linkFrontendToCiCam")) {
- if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) {
+ if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)
+ && checkCiCamResource(ciCamId)) {
return nativeLinkCiCam(ciCamId);
}
}
@@ -954,7 +948,7 @@
*/
@Result
public int disconnectCiCam() {
- if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_DEMUX)) {
+ if (mDemuxHandle != null) {
return nativeDisconnectCiCam();
}
return RESULT_UNAVAILABLE;
@@ -980,17 +974,25 @@
public int disconnectFrontendToCiCam(int ciCamId) {
if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
"unlinkFrontendToCiCam")) {
- if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) {
- return nativeUnlinkCiCam(ciCamId);
+ if (mFrontendCiCamHandle != null && mFrontendCiCamId == ciCamId) {
+ int result = nativeUnlinkCiCam(ciCamId);
+ if (result == RESULT_SUCCESS) {
+ mTunerResourceManager.releaseCiCam(mFrontendCiCamHandle, mClientId);
+ mFrontendCiCamId = null;
+ mFrontendCiCamHandle = null;
+ }
+ return result;
}
}
return RESULT_UNAVAILABLE;
}
/**
- * Gets the initialized frontend information.
+ * Gets the currently initialized and activated frontend information. To get all the available
+ * frontend info on the device, use {@link getAvailableFrontendInfos()}.
*
- * @return The frontend information. {@code null} if the operation failed.
+ * @return The active frontend information. {@code null} if the operation failed.
+ * @throws IllegalStateException if there is no active frontend currently.
*/
@Nullable
public FrontendInfo getFrontendInfo() {
@@ -1007,13 +1009,20 @@
}
/**
- * Get a list all the existed frontend information.
+ * Gets a list of all the available frontend information on the device. To get the information
+ * of the currently active frontend, use {@link getFrontendInfo()}. The active frontend
+ * information is also included in the list of the available frontend information.
*
- * @return The list of all the frontend information. {@code null} if the operation failed.
+ * @return The list of all the available frontend information. {@code null} if the operation
+ * failed.
*/
@Nullable
- public List<FrontendInfo> getFrontendInfoList() {
- return Arrays.asList(getFrontendInfoListInternal());
+ public List<FrontendInfo> getAvailableFrontendInfos() {
+ FrontendInfo[] feInfoList = getFrontendInfoListInternal();
+ if (feInfoList == null) {
+ return null;
+ }
+ return Arrays.asList(feInfoList);
}
/** @hide */
@@ -1258,7 +1267,8 @@
private boolean requestLnb() {
int[] lnbHandle = new int[1];
- TunerLnbRequest request = new TunerLnbRequest(mClientId);
+ TunerLnbRequest request = new TunerLnbRequest();
+ request.clientId = mClientId;
boolean granted = mTunerResourceManager.requestLnb(request, lnbHandle);
if (granted) {
mLnbHandle = lnbHandle[0];
@@ -1346,7 +1356,8 @@
private boolean requestDemux() {
int[] demuxHandle = new int[1];
- TunerDemuxRequest request = new TunerDemuxRequest(mClientId);
+ TunerDemuxRequest request = new TunerDemuxRequest();
+ request.clientId = mClientId;
boolean granted = mTunerResourceManager.requestDemux(request, demuxHandle);
if (granted) {
mDemuxHandle = demuxHandle[0];
@@ -1357,7 +1368,8 @@
private Descrambler requestDescrambler() {
int[] descramblerHandle = new int[1];
- TunerDescramblerRequest request = new TunerDescramblerRequest(mClientId);
+ TunerDescramblerRequest request = new TunerDescramblerRequest();
+ request.clientId = mClientId;
boolean granted = mTunerResourceManager.requestDescrambler(request, descramblerHandle);
if (!granted) {
return null;
@@ -1375,6 +1387,18 @@
return descrambler;
}
+ private boolean requestFrontendCiCam(int ciCamId) {
+ int[] ciCamHandle = new int[1];
+ TunerCiCamRequest request = new TunerCiCamRequest();
+ request.clientId = mClientId;
+ request.ciCamId = ciCamId;
+ boolean granted = mTunerResourceManager.requestCiCam(request, ciCamHandle);
+ if (granted) {
+ mFrontendCiCamHandle = ciCamHandle[0];
+ }
+ return granted;
+ }
+
private boolean checkResource(int resourceType) {
switch (resourceType) {
case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND: {
@@ -1401,6 +1425,13 @@
return true;
}
+ private boolean checkCiCamResource(int ciCamId) {
+ if (mFrontendCiCamHandle == null && !requestFrontendCiCam(ciCamId)) {
+ return false;
+ }
+ return true;
+ }
+
/* package */ void releaseLnb() {
if (mLnbHandle != null) {
// LNB handle can be null if it's opened by name.
diff --git a/media/java/android/media/tv/tunerresourcemanager/Android.bp b/media/java/android/media/tv/tunerresourcemanager/Android.bp
index c65d25a..c38d919 100644
--- a/media/java/android/media/tv/tunerresourcemanager/Android.bp
+++ b/media/java/android/media/tv/tunerresourcemanager/Android.bp
@@ -1,17 +1,28 @@
filegroup {
- name: "framework-media-tv-tunerresourcemanager-sources",
+ name: "framework-media-tv-tunerresourcemanager-sources-aidl",
srcs: [
- "*.java",
- "*.aidl",
+ "aidl/android/media/tv/tunerresourcemanager/*.aidl",
],
- path: ".",
+ path: "aidl",
}
-java_library {
- name: "framework-media-tv-trm-sources",
- srcs: [":framework-media-tv-tunerresourcemanager-sources"],
- installable: true,
- visibility: [
- "//frameworks/base",
+aidl_interface {
+ name: "tv_tuner_resource_manager_aidl_interface",
+ unstable: true,
+ local_include_dir: "aidl",
+ backend: {
+ java: {
+ enabled: true,
+ },
+ cpp: {
+ enabled: true,
+ },
+ ndk: {
+ enabled: true,
+ },
+ },
+ srcs: [
+ ":framework-media-tv-tunerresourcemanager-sources-aidl",
],
-}
\ No newline at end of file
+ imports: ["tv_tuner_frontend_info_aidl_interface"],
+}
diff --git a/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.java b/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.java
deleted file mode 100644
index 59802ff..0000000
--- a/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tunerresourcemanager;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-/**
- * Information required to request a Cas Session.
- *
- * @hide
- */
-public final class CasSessionRequest implements Parcelable {
- static final String TAG = "CasSessionRequest";
-
- public static final
- @NonNull
- Parcelable.Creator<CasSessionRequest> CREATOR =
- new Parcelable.Creator<CasSessionRequest>() {
- @Override
- public CasSessionRequest createFromParcel(Parcel source) {
- try {
- return new CasSessionRequest(source);
- } catch (Exception e) {
- Log.e(TAG, "Exception creating CasSessionRequest from parcel", e);
- return null;
- }
- }
-
- @Override
- public CasSessionRequest[] newArray(int size) {
- return new CasSessionRequest[size];
- }
- };
-
- /**
- * Client id of the client that sends the request.
- */
- private final int mClientId;
-
- /**
- * System id of the requested cas.
- */
- private final int mCasSystemId;
-
- private CasSessionRequest(@NonNull Parcel source) {
- mClientId = source.readInt();
- mCasSystemId = source.readInt();
- }
-
- /**
- * Constructs a new {@link CasSessionRequest} with the given parameters.
- *
- * @param clientId id of the client.
- * @param casSystemId the cas system id that the client is requesting.
- */
- public CasSessionRequest(int clientId,
- int casSystemId) {
- mClientId = clientId;
- mCasSystemId = casSystemId;
- }
-
- /**
- * Returns the id of the client.
- */
- public int getClientId() {
- return mClientId;
- }
-
- /**
- * Returns the cas system id requested.
- */
- public int getCasSystemId() {
- return mCasSystemId;
- }
-
- // Parcelable
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- @Override
- public String toString() {
- StringBuilder b = new StringBuilder(128);
- b.append("CasSessionRequest {clientId=").append(mClientId);
- b.append(", casSystemId=").append(mCasSystemId);
- b.append("}");
- return b.toString();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mClientId);
- dest.writeInt(mCasSystemId);
- }
-}
diff --git a/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.java b/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.java
deleted file mode 100644
index 28f1ac9..0000000
--- a/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tunerresourcemanager;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-/**
- * A profile of a resource client. This profile is used to register the client info
- * with the Tuner Resource Manager(TRM).
- *
- * @hide
- */
-public final class ResourceClientProfile implements Parcelable {
- static final String TAG = "ResourceClientProfile";
-
- public static final
- @NonNull
- Parcelable.Creator<ResourceClientProfile> CREATOR =
- new Parcelable.Creator<ResourceClientProfile>() {
- @Override
- public ResourceClientProfile createFromParcel(Parcel source) {
- try {
- return new ResourceClientProfile(source);
- } catch (Exception e) {
- Log.e(TAG, "Exception creating ResourceClientProfile from parcel", e);
- return null;
- }
- }
-
- @Override
- public ResourceClientProfile[] newArray(int size) {
- return new ResourceClientProfile[size];
- }
- };
-
- /**
- * This is used by TRM to get TV App’s processId from TIF.
- * The processId will be used to identify foreground applications.
- *
- * <p>MediaCas, Tuner and TvInputHardwareManager get tvInputSessionId from TIS.
- * If mTvInputSessionId is UNKNOWN, the client is always background.
- */
- private final String mTvInputSessionId;
-
- /**
- * Usage of the client.
- */
- private final int mUseCase;
-
- private ResourceClientProfile(@NonNull Parcel source) {
- mTvInputSessionId = source.readString();
- mUseCase = source.readInt();
- }
-
- /**
- * Constructs a new {@link ResourceClientProfile} with the given parameters.
- *
- * @param tvInputSessionId the unique id of the session owned by the client.
- * @param useCase the usage of the client. Suggested priority hints are
- * {@link android.media.tv.TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK}
- * {@link android.media.tv.TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE}
- * {@link android.media.tv.TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD}.
- * New [use case : priority value] pair can be defined in the manifest by the
- * OEM. The id of the useCaseVendor should be passed through this parameter. Any
- * undefined use case would cause IllegalArgumentException.
- */
- public ResourceClientProfile(@Nullable String tvInputSessionId,
- int useCase) {
- mTvInputSessionId = tvInputSessionId;
- mUseCase = useCase;
- }
-
- /**
- * Returns the tv input session id of the client.
- *
- * @return the value of the tv input session id.
- */
- @Nullable
- public String getTvInputSessionId() {
- return mTvInputSessionId;
- }
-
- /**
- * Returns the user usage of the client.
- *
- * @return the value of use case.
- */
- public int getUseCase() {
- return mUseCase;
- }
-
- // Parcelable
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- @Override
- public String toString() {
- StringBuilder b = new StringBuilder(128);
- b.append("ResourceClientProfile {tvInputSessionId=").append(mTvInputSessionId);
- b.append(", useCase=").append(mUseCase);
- b.append("}");
- return b.toString();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(mTvInputSessionId);
- dest.writeInt(mUseCase);
- }
-}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java
deleted file mode 100644
index 34a7761..0000000
--- a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tunerresourcemanager;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-/**
- * Information required to request a Tuner Demux.
- *
- * @hide
- */
-public final class TunerDemuxRequest implements Parcelable {
- static final String TAG = "TunerDemuxRequest";
-
- public static final
- @NonNull
- Parcelable.Creator<TunerDemuxRequest> CREATOR =
- new Parcelable.Creator<TunerDemuxRequest>() {
- @Override
- public TunerDemuxRequest createFromParcel(Parcel source) {
- try {
- return new TunerDemuxRequest(source);
- } catch (Exception e) {
- Log.e(TAG, "Exception creating TunerDemuxRequest from parcel", e);
- return null;
- }
- }
-
- @Override
- public TunerDemuxRequest[] newArray(int size) {
- return new TunerDemuxRequest[size];
- }
- };
-
- /**
- * Client id of the client that sends the request.
- */
- private final int mClientId;
-
- private TunerDemuxRequest(@NonNull Parcel source) {
- mClientId = source.readInt();
- }
-
- /**
- * Constructs a new {@link TunerDemuxRequest} with the given parameters.
- *
- * @param clientId id of the client.
- */
- public TunerDemuxRequest(int clientId) {
- mClientId = clientId;
- }
-
- /**
- * Returns the id of the client.
- */
- public int getClientId() {
- return mClientId;
- }
-
- // Parcelable
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- @Override
- public String toString() {
- StringBuilder b = new StringBuilder(128);
- b.append("TunerDemuxRequest {clientId=").append(mClientId);
- b.append("}");
- return b.toString();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mClientId);
- }
-}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java
deleted file mode 100644
index 5816287..0000000
--- a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tunerresourcemanager;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-/**
- * Information required to request a Tuner Descrambler.
- *
- * @hide
- */
-public final class TunerDescramblerRequest implements Parcelable {
- static final String TAG = "TunerDescramblerRequest";
-
- public static final
- @NonNull
- Parcelable.Creator<TunerDescramblerRequest> CREATOR =
- new Parcelable.Creator<TunerDescramblerRequest>() {
- @Override
- public TunerDescramblerRequest createFromParcel(Parcel source) {
- try {
- return new TunerDescramblerRequest(source);
- } catch (Exception e) {
- Log.e(TAG, "Exception creating TunerDescramblerRequest from parcel", e);
- return null;
- }
- }
-
- @Override
- public TunerDescramblerRequest[] newArray(int size) {
- return new TunerDescramblerRequest[size];
- }
- };
-
- /**
- * Client id of the client that sends the request.
- */
- private final int mClientId;
-
- private TunerDescramblerRequest(@NonNull Parcel source) {
- mClientId = source.readInt();
- }
-
- /**
- * Constructs a new {@link TunerDescramblerRequest} with the given parameters.
- *
- * @param clientId id of the client.
- */
- public TunerDescramblerRequest(int clientId) {
- mClientId = clientId;
- }
-
- /**
- * Returns the id of the client.
- */
- public int getClientId() {
- return mClientId;
- }
-
- // Parcelable
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- @Override
- public String toString() {
- StringBuilder b = new StringBuilder(128);
- b.append("TunerDescramblerRequest {clientId=").append(mClientId);
- b.append("}");
- return b.toString();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mClientId);
- }
-}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl b/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
deleted file mode 100644
index e649c2a..0000000
--- a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tunerresourcemanager;
-
-/**
- * Simple container of the FrontendInfo struct defined in the TunerHAL 1.0 interface.
- *
- * @hide
- */
-parcelable TunerFrontendInfo;
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.java b/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.java
deleted file mode 100644
index ef50aac..0000000
--- a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendInfo.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tunerresourcemanager;
-
-import android.annotation.NonNull;
-import android.media.tv.tuner.frontend.FrontendSettings.Type;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-/**
- * Simple container of the FrontendInfo struct defined in the TunerHAL 1.0 interface.
- *
- * <p>Note that this object is defined to pass necessary frontend info between the
- * Tuner Resource Manager and the client. It includes partial information in
- * {@link FrontendInfo}.
- *
- * @hide
- */
-public final class TunerFrontendInfo implements Parcelable {
- static final String TAG = "TunerFrontendInfo";
-
- public static final
- @NonNull
- Parcelable.Creator<TunerFrontendInfo> CREATOR =
- new Parcelable.Creator<TunerFrontendInfo>() {
- @Override
- public TunerFrontendInfo createFromParcel(Parcel source) {
- try {
- return new TunerFrontendInfo(source);
- } catch (Exception e) {
- Log.e(TAG, "Exception creating TunerFrontendInfo from parcel", e);
- return null;
- }
- }
-
- @Override
- public TunerFrontendInfo[] newArray(int size) {
- return new TunerFrontendInfo[size];
- }
- };
-
- private final int mHandle;
-
- @Type
- private final int mFrontendType;
-
- /**
- * Frontends are assigned with the same exclusiveGroupId if they can't
- * function at same time. For instance, they share same hardware module.
- */
- private final int mExclusiveGroupId;
-
- private TunerFrontendInfo(@NonNull Parcel source) {
- mHandle = source.readInt();
- mFrontendType = source.readInt();
- mExclusiveGroupId = source.readInt();
- }
-
- /**
- * Constructs a new {@link TunerFrontendInfo} with the given parameters.
- *
- * @param handle frontend handle
- * @param frontendType the type of the frontend.
- * @param exclusiveGroupId the group id of the frontend. FE with the same
- group id can't function at the same time.
- */
- public TunerFrontendInfo(int handle,
- @Type int frontendType,
- int exclusiveGroupId) {
- mHandle = handle;
- mFrontendType = frontendType;
- mExclusiveGroupId = exclusiveGroupId;
- }
-
- /**
- * Returns the frontend handle.
- *
- * @return the value of the frontend handle.
- */
- public int getHandle() {
- return mHandle;
- }
-
- /**
- * Returns the application id that requests the tuner frontend resource.
- *
- * @return the value of the frontend type.
- */
- @Type
- public int getFrontendType() {
- return mFrontendType;
- }
-
- /**
- * Returns the exclusiveGroupId. Frontends with the same exclusiveGroupId
- * can't function at same time.
- *
- * @return the value of the exclusive group id.
- */
- public int getExclusiveGroupId() {
- return mExclusiveGroupId;
- }
-
- // Parcelable
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- @Override
- public String toString() {
- StringBuilder b = new StringBuilder(128);
- b.append("TunerFrontendInfo {handle=").append(mHandle);
- b.append(", frontendType=").append(mFrontendType);
- b.append(", exclusiveGroupId=").append(mExclusiveGroupId);
- b.append("}");
- return b.toString();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mHandle);
- dest.writeInt(mFrontendType);
- dest.writeInt(mExclusiveGroupId);
- }
-}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.java
deleted file mode 100644
index 12f8032..0000000
--- a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tunerresourcemanager;
-
-import android.annotation.NonNull;
-import android.media.tv.tuner.frontend.FrontendSettings.Type;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-/**
- * Information required to request a Tuner Frontend.
- *
- * @hide
- */
-public final class TunerFrontendRequest implements Parcelable {
- static final String TAG = "TunerFrontendRequest";
-
- public static final
- @NonNull
- Parcelable.Creator<TunerFrontendRequest> CREATOR =
- new Parcelable.Creator<TunerFrontendRequest>() {
- @Override
- public TunerFrontendRequest createFromParcel(Parcel source) {
- try {
- return new TunerFrontendRequest(source);
- } catch (Exception e) {
- Log.e(TAG, "Exception creating TunerFrontendRequest from parcel", e);
- return null;
- }
- }
-
- @Override
- public TunerFrontendRequest[] newArray(int size) {
- return new TunerFrontendRequest[size];
- }
- };
-
- private final int mClientId;
- @Type
- private final int mFrontendType;
-
- private TunerFrontendRequest(@NonNull Parcel source) {
- mClientId = source.readInt();
- mFrontendType = source.readInt();
- }
-
- /**
- * Constructs a new {@link TunerFrontendRequest} with the given parameters.
- *
- * @param clientId the unique id of the client returned when registering profile.
- * @param frontendType the type of the requested frontend.
- */
- public TunerFrontendRequest(int clientId,
- @Type int frontendType) {
- mClientId = clientId;
- mFrontendType = frontendType;
- }
-
- /**
- * Returns the client id that requests the tuner frontend resource.
- *
- * @return the value of the client id.
- */
- public int getClientId() {
- return mClientId;
- }
-
- /**
- * Returns the frontend type that the client requests for.
- *
- * @return the value of the requested frontend type.
- */
- @Type
- public int getFrontendType() {
- return mFrontendType;
- }
-
- // Parcelable
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- @Override
- public String toString() {
- StringBuilder b = new StringBuilder(128);
- b.append("TunerFrontendRequest {clientId=").append(mClientId);
- b.append(", frontendType=").append(mFrontendType);
- b.append("}");
- return b.toString();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mClientId);
- dest.writeInt(mFrontendType);
- }
-}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.java b/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.java
deleted file mode 100644
index 5ed7f3f..0000000
--- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.tv.tunerresourcemanager;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-/**
- * Information required to request a Tuner Lnb.
- *
- * @hide
- */
-public final class TunerLnbRequest implements Parcelable {
- static final String TAG = "TunerLnbRequest";
-
- public static final
- @NonNull
- Parcelable.Creator<TunerLnbRequest> CREATOR =
- new Parcelable.Creator<TunerLnbRequest>() {
- @Override
- public TunerLnbRequest createFromParcel(Parcel source) {
- try {
- return new TunerLnbRequest(source);
- } catch (Exception e) {
- Log.e(TAG, "Exception creating TunerLnbRequest from parcel", e);
- return null;
- }
- }
-
- @Override
- public TunerLnbRequest[] newArray(int size) {
- return new TunerLnbRequest[size];
- }
- };
-
- /**
- * Client id of the client that sends the request.
- */
- private final int mClientId;
-
- private TunerLnbRequest(@NonNull Parcel source) {
- mClientId = source.readInt();
- }
-
- /**
- * Constructs a new {@link TunerLnbRequest} with the given parameters.
- *
- * @param clientId the id of the client.
- */
- public TunerLnbRequest(int clientId) {
- mClientId = clientId;
- }
-
- /**
- * Returns the id of the client
- */
- public int getClientId() {
- return mClientId;
- }
-
- // Parcelable
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- @Override
- public String toString() {
- StringBuilder b = new StringBuilder(128);
- b.append("TunerLnbRequest {clientId=").append(mClientId);
- b.append("}");
- return b.toString();
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(mClientId);
- }
-}
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index be102d8..e399fbd 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -24,6 +24,7 @@
import android.annotation.SystemService;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.media.tv.tuner.TunerFrontendInfo;
import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
@@ -74,6 +75,7 @@
TUNER_RESOURCE_TYPE_DESCRAMBLER,
TUNER_RESOURCE_TYPE_LNB,
TUNER_RESOURCE_TYPE_CAS_SESSION,
+ TUNER_RESOURCE_TYPE_FRONTEND_CICAM,
TUNER_RESOURCE_TYPE_MAX,
})
@Retention(RetentionPolicy.SOURCE)
@@ -84,7 +86,8 @@
public static final int TUNER_RESOURCE_TYPE_DESCRAMBLER = 2;
public static final int TUNER_RESOURCE_TYPE_LNB = 3;
public static final int TUNER_RESOURCE_TYPE_CAS_SESSION = 4;
- public static final int TUNER_RESOURCE_TYPE_MAX = 5;
+ public static final int TUNER_RESOURCE_TYPE_FRONTEND_CICAM = 5;
+ public static final int TUNER_RESOURCE_TYPE_MAX = 6;
private final ITunerResourceManager mService;
private final int mUserId;
@@ -379,6 +382,38 @@
}
/**
+ * Requests a CiCam resource.
+ *
+ * <p>There are three possible scenarios:
+ * <ul>
+ * <li>If there is CiCam available, the API would send the id back.
+ *
+ * <li>If no CiCam is available but the current request info can show higher priority than
+ * other uses of the CiCam, the API will send
+ * {@link IResourcesReclaimListener#onReclaimResources()} to the {@link Tuner}. Tuner would
+ * handle the resource reclaim on the holder of lower priority and notify the holder of its
+ * resource loss.
+ *
+ * <p><strong>Note:</strong> {@link #updateCasInfo(int, int)} must be called before this
+ * request.
+ *
+ * @param request {@link TunerCiCamRequest} information of the current request.
+ * @param ciCamHandle a one-element array to return the granted ciCam handle.
+ * If no ciCam granted, this will return {@link #INVALID_RESOURCE_HANDLE}.
+ *
+ * @return true if there is ciCam granted.
+ */
+ public boolean requestCiCam(TunerCiCamRequest request, int[] ciCamHandle) {
+ boolean result = false;
+ try {
+ result = mService.requestCiCam(request, ciCamHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ return result;
+ }
+
+ /**
* Requests a Tuner Lnb resource.
*
* <p>There are three possible scenarios:
@@ -482,6 +517,25 @@
}
/**
+ * Notifies the TRM that the given CiCam has been released.
+ *
+ * <p>Client must call this whenever it releases a CiCam.
+ *
+ * <p><strong>Note:</strong> {@link #updateCasInfo(int, int)} must be called before this
+ * release.
+ *
+ * @param ciCamHandle the handle of the releasing CiCam.
+ * @param clientId the id of the client that is releasing the CiCam.
+ */
+ public void releaseCiCam(int ciCamHandle, int clientId) {
+ try {
+ mService.releaseCiCam(ciCamHandle, clientId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Notifies the TRM that the Lnb with the given id has been released.
*
* <p>Client must call this whenever it releases an Lnb.
diff --git a/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl
similarity index 91%
rename from media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl
rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl
index c918d88..88f5915 100644
--- a/media/java/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/CasSessionRequest.aidl
@@ -21,4 +21,8 @@
*
* @hide
*/
-parcelable CasSessionRequest;
\ No newline at end of file
+parcelable CasSessionRequest {
+ int clientId;
+
+ int casSystemId;
+}
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl
similarity index 100%
rename from media/java/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl
rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/IResourcesReclaimListener.aidl
diff --git a/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
similarity index 88%
rename from media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
index 487b444..483d972 100644
--- a/media/java/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
@@ -16,12 +16,13 @@
package android.media.tv.tunerresourcemanager;
+import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
-import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
@@ -225,6 +226,31 @@
boolean requestCasSession(in CasSessionRequest request, out int[] casSessionHandle);
/*
+ * This API is used by the Tuner framework to request an available CuCam.
+ *
+ * <p>There are three possible scenarios:
+ * <ul>
+ * <li>If there is CiCam available, the API would send the handle back.
+ *
+ * <li>If no CiCma is available but the current request info can show higher priority than
+ * other uses of the ciCam, the API will send
+ * {@link ITunerResourceManagerCallback#onReclaimResources()} to the {@link Tuner}. Tuner would
+ * handle the resource reclaim on the holder of lower priority and notify the holder of its
+ * resource loss.
+ *
+ * <li>If no CiCam can be granted, the API would return false.
+ * <ul>
+ *
+ * <p><strong>Note:</strong> {@link #updateCasInfo(int, int)} must be called before this request.
+ *
+ * @param request {@link TunerCiCamRequest} information of the current request.
+ * @param ciCamHandle a one-element array to return the granted ciCam handle.
+ *
+ * @return true if there is CiCam granted.
+ */
+ boolean requestCiCam(in TunerCiCamRequest request, out int[] ciCamHandle);
+
+ /*
* This API is used by the Tuner framework to request an available Lnb from the TunerHAL.
*
* <p>There are three possible scenarios:
@@ -293,6 +319,19 @@
*/
void releaseCasSession(in int casSessionHandle, int clientId);
+ /**
+ * Notifies the TRM that the given CiCam has been released.
+ *
+ * <p>Client must call this whenever it releases a CiCam.
+ *
+ * <p><strong>Note:</strong> {@link #updateCasInfo(int, int)} must be called before this
+ * release.
+ *
+ * @param ciCamHandle the handle of the releasing CiCam.
+ * @param clientId the id of the client that is releasing the CiCam.
+ */
+ void releaseCiCam(in int ciCamHandle, int clientId);
+
/*
* Notifies the TRM that the Lnb with the given handle was released.
*
diff --git a/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl
similarity index 90%
rename from media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl
rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl
index ed90c1d..08c2bb8 100644
--- a/media/java/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ResourceClientProfile.aidl
@@ -22,4 +22,8 @@
*
* @hide
*/
-parcelable ResourceClientProfile;
\ No newline at end of file
+parcelable ResourceClientProfile {
+ String tvInputSessionId;
+
+ int useCase;
+}
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerCiCamRequest.aidl
similarity index 81%
copy from media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
copy to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerCiCamRequest.aidl
index 919a215..76f9f83 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerCiCamRequest.aidl
@@ -17,8 +17,12 @@
package android.media.tv.tunerresourcemanager;
/**
- * Information required to request a Tuner Demux.
+ * A wrapper of a ciCam requests that contains all the request info of the client.
*
* @hide
*/
-parcelable TunerDemuxRequest;
\ No newline at end of file
+parcelable TunerCiCamRequest {
+ int clientId;
+
+ int ciCamId;
+}
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
similarity index 93%
rename from media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
index 919a215..457f90c 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDemuxRequest.aidl
@@ -21,4 +21,6 @@
*
* @hide
*/
-parcelable TunerDemuxRequest;
\ No newline at end of file
+parcelable TunerDemuxRequest {
+ int clientId;
+}
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl
similarity index 92%
rename from media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl
rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl
index fbafb3b..98ab730 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerDescramblerRequest.aidl
@@ -21,4 +21,6 @@
*
* @hide
*/
-parcelable TunerDescramblerRequest;
\ No newline at end of file
+parcelable TunerDescramblerRequest {
+ int clientId;
+}
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl
similarity index 90%
rename from media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl
rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl
index 5e48adc..4d98222 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerFrontendRequest.aidl
@@ -21,4 +21,8 @@
*
* @hide
*/
-parcelable TunerFrontendRequest;
\ No newline at end of file
+parcelable TunerFrontendRequest {
+ int clientId;
+
+ int frontendType;
+}
\ No newline at end of file
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
similarity index 93%
rename from media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
rename to media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
index 0e6fcde..1a059ea 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/TunerLnbRequest.aidl
@@ -21,4 +21,6 @@
*
* @hide
*/
-parcelable TunerLnbRequest;
\ No newline at end of file
+parcelable TunerLnbRequest {
+ int clientId;
+}
\ No newline at end of file
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index f80f412..decf68f 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -137,6 +137,7 @@
cc_library_shared {
name: "libmedia_tv_tuner",
+
srcs: [
"android_media_tv_Tuner.cpp",
"tuner/DemuxClient.cpp",
@@ -163,6 +164,7 @@
"libnativehelper",
"libutils",
"tv_tuner_aidl_interface-ndk_platform",
+ "tv_tuner_resource_manager_aidl_interface-ndk_platform"
],
defaults: [
"libcodec2-impl-defaults",
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
index 14761a6..d6d64f6 100644
--- a/media/jni/tuner/FrontendClient.cpp
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -21,18 +21,39 @@
#include "FrontendClient.h"
+using ::aidl::android::media::tv::tuner::TunerFrontendScanAtsc3PlpInfo;
using ::aidl::android::media::tv::tuner::TunerFrontendSettings;
+
+using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
+using ::android::hardware::tv::tuner::V1_0::FrontendAnalogType;
+using ::android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendAtsc3Modulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbcAnnex;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbcModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbsModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbsStandard;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
+using ::android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
+using ::android::hardware::tv::tuner::V1_0::FrontendIsdbsModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendIsdbs3Modulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendIsdbtModulation;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanAtsc3PlpInfo;
+using ::android::hardware::tv::tuner::V1_0::FrontendType;
using ::android::hardware::tv::tuner::V1_1::Constant;
+using ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation;
+using ::android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation;
+using ::android::hardware::tv::tuner::V1_1::FrontendModulation;
namespace android {
/////////////// FrontendClient ///////////////////////
-FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int id) {
+FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int id, int type) {
mTunerFrontend = tunerFrontend;
mAidlCallback = NULL;
mHidlCallback = NULL;
mId = id;
+ mType = type;
}
FrontendClient::~FrontendClient() {
@@ -42,11 +63,13 @@
mAidlCallback = NULL;
mHidlCallback = NULL;
mId = -1;
+ mType = -1;
}
Result FrontendClient::setCallback(sp<FrontendClientCallback> frontendClientCallback) {
if (mTunerFrontend != NULL) {
mAidlCallback = ::ndk::SharedRefBase::make<TunerFrontendCallback>(frontendClientCallback);
+ mAidlCallback->setFrontendType(mType);
mTunerFrontend->setCallback(mAidlCallback);
return Result::SUCCESS;
}
@@ -298,56 +321,21 @@
return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
-Status TunerFrontendCallback::onLocked() {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onScanStopped() {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onProgress(int /*percent*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onFrequenciesReport(const vector<int>& /*frequency*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onSymbolRates(const vector<int>& /*rates*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onHierarchy(int /*hierarchy*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onSignalType(int /*signalType*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onPlpIds(const vector<int>& /*plpIds*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onGroupIds(const vector<int>& /*groupIds*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onInputStreamIds(const vector<int>& /*inputStreamIds*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onDvbsStandard(int /*dvbsStandandard*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onAnalogSifStandard(int /*sifStandandard*/) {
- return Status::ok();
-}
-
-Status TunerFrontendCallback::onAtsc3PlpInfos(const vector<TunerAtsc3PlpInfo>& /*atsc3PlpInfos*/) {
- return Status::ok();
+Status TunerFrontendCallback::onScanMessage(int messageType,
+ const TunerFrontendScanMessage& message) {
+ if (mFrontendClientCallback != NULL) {
+ if (!is1_1ExtendedScanMessage(messageType)) {
+ mFrontendClientCallback->onScanMessage(
+ static_cast<FrontendScanMessageType>(messageType),
+ getHalScanMessage(messageType, message));
+ } else {
+ mFrontendClientCallback->onScanMessageExt1_1(
+ static_cast<FrontendScanMessageTypeExt1_1>(messageType),
+ getHalScanMessageExt1_1(messageType, message));
+ }
+ return Status::ok();
+ }
+ return Status::fromServiceSpecificError(static_cast<int32_t>(Result::INVALID_STATE));
}
/////////////// IFrontendCallback ///////////////////////
@@ -377,4 +365,167 @@
}
return Void();
}
+
+/////////////// FrontendClientCallback Helper Methods ///////////////////////
+
+FrontendScanMessage TunerFrontendCallback::getHalScanMessage(
+ int messageType, const TunerFrontendScanMessage& message) {
+ FrontendScanMessage scanMessage;
+ switch (messageType) {
+ case (int) FrontendScanMessageType::LOCKED:
+ scanMessage.isLocked(message.get<TunerFrontendScanMessage::isLocked>());
+ break;
+ case (int) FrontendScanMessageType::END:
+ scanMessage.isEnd(message.get<TunerFrontendScanMessage::isEnd>());
+ break;
+ case (int) FrontendScanMessageType::PROGRESS_PERCENT:
+ scanMessage.progressPercent(message.get<TunerFrontendScanMessage::progressPercent>());
+ break;
+ case (int) FrontendScanMessageType::FREQUENCY: {
+ vector<int> f = message.get<TunerFrontendScanMessage::frequencies>();
+ hidl_vec<uint32_t> frequencies(begin(f), end(f));
+ scanMessage.frequencies(frequencies);
+ break;
+ }
+ case (int) FrontendScanMessageType::SYMBOL_RATE: {
+ vector<int> s = message.get<TunerFrontendScanMessage::symbolRates>();
+ hidl_vec<uint32_t> symbolRates(begin(s), end(s));
+ scanMessage.symbolRates(symbolRates);
+ break;
+ }
+ case (int) FrontendScanMessageType::HIERARCHY:
+ scanMessage.hierarchy(static_cast<FrontendDvbtHierarchy>(
+ message.get<TunerFrontendScanMessage::hierarchy>()));
+ break;
+ case (int) FrontendScanMessageType::ANALOG_TYPE:
+ scanMessage.analogType(static_cast<FrontendAnalogType>(
+ message.get<TunerFrontendScanMessage::analogType>()));
+ break;
+ case (int) FrontendScanMessageType::PLP_IDS: {
+ vector<uint8_t> p = message.get<TunerFrontendScanMessage::plpIds>();
+ hidl_vec<uint8_t> plpIds(begin(p), end(p));
+ scanMessage.plpIds(plpIds);
+ break;
+ }
+ case (int) FrontendScanMessageType::GROUP_IDS: {
+ vector<uint8_t> g = message.get<TunerFrontendScanMessage::groupIds>();
+ hidl_vec<uint8_t> groupIds(begin(g), end(g));
+ scanMessage.groupIds(groupIds);
+ break;
+ }
+ case (int) FrontendScanMessageType::INPUT_STREAM_IDS: {
+ vector<char16_t> i = message.get<TunerFrontendScanMessage::inputStreamIds>();
+ hidl_vec<uint16_t> inputStreamIds(begin(i), end(i));
+ scanMessage.inputStreamIds(inputStreamIds);
+ break;
+ }
+ case (int) FrontendScanMessageType::STANDARD: {
+ FrontendScanMessage::Standard std;
+ int standard = message.get<TunerFrontendScanMessage::std>();
+ switch (mType) {
+ case (int) FrontendType::DVBS:
+ std.sStd(static_cast<FrontendDvbsStandard>(standard));
+ scanMessage.std(std);
+ break;
+ case (int) FrontendType::DVBT:
+ std.tStd(static_cast<FrontendDvbtStandard>(standard));
+ scanMessage.std(std);
+ break;
+ case (int) FrontendType::ANALOG:
+ std.sifStd(static_cast<FrontendAnalogSifStandard>(standard));
+ scanMessage.std(std);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case (int) FrontendScanMessageType::ATSC3_PLP_INFO: {
+ vector<TunerFrontendScanAtsc3PlpInfo> plp =
+ message.get<TunerFrontendScanMessage::atsc3PlpInfos>();
+ hidl_vec<FrontendScanAtsc3PlpInfo> plpInfo;
+ for (TunerFrontendScanAtsc3PlpInfo info : plp) {
+ FrontendScanAtsc3PlpInfo p{
+ .plpId = static_cast<uint8_t>(info.plpId),
+ .bLlsFlag = info.llsFlag,
+ };
+ int size = plpInfo.size();
+ plpInfo.resize(size + 1);
+ plpInfo[size] = p;
+ }
+ scanMessage.atsc3PlpInfos(plpInfo);
+ break;
+ }
+ default:
+ break;
+ }
+ return scanMessage;
+}
+
+FrontendScanMessageExt1_1 TunerFrontendCallback::getHalScanMessageExt1_1(
+ int messageType, const TunerFrontendScanMessage& message) {
+ FrontendScanMessageExt1_1 scanMessage;
+ switch (messageType) {
+ case (int) FrontendScanMessageTypeExt1_1::HIGH_PRIORITY:
+ scanMessage.isHighPriority(message.get<TunerFrontendScanMessage::isHighPriority>());
+ break;
+ case (int) FrontendScanMessageTypeExt1_1::DVBC_ANNEX:
+ scanMessage.annex(static_cast<FrontendDvbcAnnex>(
+ message.get<TunerFrontendScanMessage::annex>()));
+ break;
+ case (int) FrontendScanMessageTypeExt1_1::MODULATION: {
+ FrontendModulation m;
+ int modulation = message.get<TunerFrontendScanMessage::modulation>();
+ switch (mType) {
+ case (int) FrontendType::DVBC:
+ m.dvbc(static_cast<FrontendDvbcModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::DVBS:
+ m.dvbs(static_cast<FrontendDvbsModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::DVBT:
+ m.dvbt(static_cast<FrontendDvbtConstellation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ISDBS:
+ m.isdbs(static_cast<FrontendIsdbsModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ISDBS3:
+ m.isdbs3(static_cast<FrontendIsdbs3Modulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ISDBT:
+ m.isdbt(static_cast<FrontendIsdbtModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ATSC:
+ m.atsc(static_cast<FrontendAtscModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) FrontendType::ATSC3:
+ m.atsc3(static_cast<FrontendAtsc3Modulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ case (int) hardware::tv::tuner::V1_1::FrontendType::DTMB:
+ m.dtmb(static_cast<FrontendDtmbModulation>(modulation));
+ scanMessage.modulation(m);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return scanMessage;
+}
+
+bool TunerFrontendCallback::is1_1ExtendedScanMessage(int messageType) {
+ return messageType >= (int)FrontendScanMessageTypeExt1_1::MODULATION
+ && messageType <= (int)FrontendScanMessageTypeExt1_1::HIGH_PRIORITY;
+}
} // namespace android
diff --git a/media/jni/tuner/FrontendClient.h b/media/jni/tuner/FrontendClient.h
index 32356744..4f95c22 100644
--- a/media/jni/tuner/FrontendClient.h
+++ b/media/jni/tuner/FrontendClient.h
@@ -30,7 +30,7 @@
using ::aidl::android::media::tv::tuner::BnTunerFrontendCallback;
using ::aidl::android::media::tv::tuner::ITunerFrontend;
-using ::aidl::android::media::tv::tuner::TunerAtsc3PlpInfo;
+using ::aidl::android::media::tv::tuner::TunerFrontendScanMessage;
using ::android::hardware::Return;
using ::android::hardware::Void;
@@ -63,34 +63,18 @@
Status onEvent(int frontendEventType);
- Status onLocked();
+ Status onScanMessage(int messageType, const TunerFrontendScanMessage& message);
- Status onScanStopped();
-
- Status onProgress(int percent);
-
- Status onFrequenciesReport(const vector<int>& frequency);
-
- Status onSymbolRates(const vector<int>& rates);
-
- Status onHierarchy(int hierarchy);
-
- Status onSignalType(int signalType);
-
- Status onPlpIds(const vector<int>& plpIds);
-
- Status onGroupIds(const vector<int>& groupIds);
-
- Status onInputStreamIds(const vector<int>& inputStreamIds);
-
- Status onDvbsStandard(int dvbsStandandard);
-
- Status onAnalogSifStandard(int sifStandandard);
-
- Status onAtsc3PlpInfos(const vector<TunerAtsc3PlpInfo>& atsc3PlpInfos);
+ void setFrontendType(int frontendType) { mType = frontendType; }
private:
+ FrontendScanMessage getHalScanMessage(int messageType, const TunerFrontendScanMessage& message);
+ FrontendScanMessageExt1_1 getHalScanMessageExt1_1(int messageType,
+ const TunerFrontendScanMessage& message);
+ bool is1_1ExtendedScanMessage(int messageType);
+
sp<FrontendClientCallback> mFrontendClientCallback;
+ int mType;
};
struct HidlFrontendCallback : public IFrontendCallback {
@@ -111,7 +95,7 @@
struct FrontendClient : public RefBase {
public:
- FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int id);
+ FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int id, int type);
~FrontendClient();
/**
@@ -210,6 +194,7 @@
sp<HidlFrontendCallback> mHidlCallback;
int mId;
+ int mType;
};
} // namespace android
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index b14e902..f5e3524 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -37,6 +37,7 @@
TunerClient::TunerClient() {
// Get HIDL Tuner in migration stage.
getHidlTuner();
+ updateTunerResources();
// Connect with Tuner Service.
::ndk::SpAIBinder binder(AServiceManager_getService("media.tuner"));
mTunerService = ITunerService::fromBinder(binder);
@@ -95,14 +96,28 @@
// TODO: handle error code
shared_ptr<ITunerFrontend> tunerFrontend;
mTunerService->openFrontend(frontendHandle, &tunerFrontend);
- return new FrontendClient(tunerFrontend, frontendHandle);
+ if (tunerFrontend == NULL) {
+ return NULL;
+ }
+ int id;
+ // TODO: handle error code
+ tunerFrontend->getFrontendId(&id);
+ TunerFrontendInfo aidlFrontendInfo;
+ // TODO: handle error code
+ mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
+ return new FrontendClient(tunerFrontend, frontendHandle, aidlFrontendInfo.type);
}
if (mTuner != NULL) {
int id = getResourceIdFromHandle(frontendHandle, FRONTEND);
sp<IFrontend> hidlFrontend = openHidlFrontendById(id);
if (hidlFrontend != NULL) {
- sp<FrontendClient> frontendClient = new FrontendClient(NULL, id);
+ FrontendInfo hidlInfo;
+ Result res = getHidlFrontendInfo(id, hidlInfo);
+ if (res != Result::SUCCESS) {
+ return NULL;
+ }
+ sp<FrontendClient> frontendClient = new FrontendClient(NULL, id, (int)hidlInfo.type);
frontendClient->setHidlFrontend(hidlFrontend);
return frontendClient;
}
@@ -113,7 +128,7 @@
shared_ptr<FrontendInfo> TunerClient::getFrontendInfo(int id) {
if (mTunerService != NULL) {
- TunerServiceFrontendInfo aidlFrontendInfo;
+ TunerFrontendInfo aidlFrontendInfo;
// TODO: handle error code
mTunerService->getFrontendInfo(id, &aidlFrontendInfo);
return make_shared<FrontendInfo>(FrontendInfoAidlToHidl(aidlFrontendInfo));
@@ -259,6 +274,49 @@
/////////////// TunerClient Helper Methods ///////////////////////
+void TunerClient::updateTunerResources() {
+ if (mTuner == NULL) {
+ return;
+ }
+
+ // Connect with Tuner Resource Manager.
+ ::ndk::SpAIBinder binder(AServiceManager_getService("tv_tuner_resource_mgr"));
+ mTunerResourceManager = ITunerResourceManager::fromBinder(binder);
+
+ updateFrontendResources();
+ updateLnbResources();
+ // TODO: update Demux, Descrambler.
+}
+
+void TunerClient::updateFrontendResources() {
+ vector<FrontendId> ids = getFrontendIds();
+ if (ids.size() == 0) {
+ return;
+ }
+ vector<TunerFrontendInfo> infos;
+ for (int i = 0; i < ids.size(); i++) {
+ shared_ptr<FrontendInfo> frontendInfo = getFrontendInfo((int)ids[i]);
+ if (frontendInfo == NULL) {
+ continue;
+ }
+ TunerFrontendInfo tunerFrontendInfo{
+ .handle = getResourceHandleFromId((int)ids[i], FRONTEND),
+ .type = static_cast<int>(frontendInfo->type),
+ .exclusiveGroupId = static_cast<int>(frontendInfo->exclusiveGroupId),
+ };
+ infos.push_back(tunerFrontendInfo);
+ }
+ mTunerResourceManager->setFrontendInfoList(infos);
+}
+
+void TunerClient::updateLnbResources() {
+ vector<int> handles = getLnbHandles();
+ if (handles.size() == 0) {
+ return;
+ }
+ mTunerResourceManager->setLnbInfoList(handles);
+}
+
sp<ITuner> TunerClient::getHidlTuner() {
if (mTuner == NULL) {
mTunerVersion = 0;
@@ -366,7 +424,33 @@
return descrambler;
}
-FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo) {
+vector<int> TunerClient::getLnbHandles() {
+ vector<int> lnbHandles;
+
+ if (mTunerService != NULL) {
+ // TODO: pending hidl interface
+ }
+
+ if (mTuner != NULL) {
+ Result res;
+ vector<LnbId> lnbIds;
+ mTuner->getLnbIds([&](Result r, const hardware::hidl_vec<LnbId>& ids) {
+ lnbIds = ids;
+ res = r;
+ });
+ if (res != Result::SUCCESS || lnbIds.size() == 0) {
+ ALOGW("Lnb isn't available");
+ } else {
+ for (int i = 0; i < lnbIds.size(); i++) {
+ lnbHandles.push_back(getResourceHandleFromId((int)lnbIds[i], LNB));
+ }
+ }
+ }
+
+ return lnbHandles;
+}
+
+FrontendInfo TunerClient::FrontendInfoAidlToHidl(TunerFrontendInfo aidlFrontendInfo) {
FrontendInfo hidlFrontendInfo {
.type = static_cast<FrontendType>(aidlFrontendInfo.type),
.minFrequency = static_cast<uint32_t>(aidlFrontendInfo.minFrequency),
diff --git a/media/jni/tuner/TunerClient.h b/media/jni/tuner/TunerClient.h
index 94fdf27..8a1181a 100644
--- a/media/jni/tuner/TunerClient.h
+++ b/media/jni/tuner/TunerClient.h
@@ -17,7 +17,9 @@
#ifndef _ANDROID_MEDIA_TV_TUNER_CLIENT_H_
#define _ANDROID_MEDIA_TV_TUNER_CLIENT_H_
+#include <aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.h>
#include <aidl/android/media/tv/tuner/ITunerService.h>
+#include <aidl/android/media/tv/tuner/TunerFrontendInfo.h>
#include <android/hardware/tv/tuner/1.1/ITuner.h>
#include <android/hardware/tv/tuner/1.1/types.h>
@@ -27,11 +29,13 @@
#include "LnbClient.h"
using ::aidl::android::media::tv::tuner::ITunerService;
-using ::aidl::android::media::tv::tuner::TunerServiceFrontendInfo;
+using ::aidl::android::media::tv::tuner::TunerFrontendInfo;
+using ::aidl::android::media::tv::tunerresourcemanager::ITunerResourceManager;
using ::android::hardware::tv::tuner::V1_0::DemuxCapabilities;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::ITuner;
+using ::android::hardware::tv::tuner::V1_0::LnbId;
using ::android::hardware::tv::tuner::V1_0::Result;
using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities;
@@ -136,13 +140,16 @@
sp<ILnb> openHidlLnbById(int id);
sp<ILnb> openHidlLnbByName(string name, LnbId& lnbId);
sp<IDescrambler> openHidlDescrambler();
- FrontendInfo FrontendInfoAidlToHidl(TunerServiceFrontendInfo aidlFrontendInfo);
+ vector<int> getLnbHandles();
+ FrontendInfo FrontendInfoAidlToHidl(TunerFrontendInfo aidlFrontendInfo);
+ void updateTunerResources();
+ void updateFrontendResources();
+ void updateLnbResources();
int getResourceIdFromHandle(int handle, int resourceType);
int getResourceHandleFromId(int id, int resourceType);
-private:
/**
* An AIDL Tuner Service Singleton assigned at the first time the Tuner Client
* connects with the Tuner Service. Default null when the service does not exist.
@@ -167,6 +174,8 @@
// while the low 16 bits are the minor version. Default value is unknown version 0.
static int mTunerVersion;
+ shared_ptr<ITunerResourceManager> mTunerResourceManager;
+
int mResourceRequestCount = 0;
};
} // namespace android
diff --git a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
index 7017e44..5005c46 100644
--- a/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
+++ b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
@@ -296,7 +296,7 @@
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
mSettingsPendingIntent = PendingIntent.getActivity(
- mContext, 0, settingsIntent, 0, null);
+ mContext, 0, settingsIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED, null);
}
return mSettingsPendingIntent;
}
diff --git a/native/android/include_platform/android/activity_manager.h b/native/android/include_platform/android/activity_manager.h
index 0ecd56d..aa86c74 100644
--- a/native/android/include_platform/android/activity_manager.h
+++ b/native/android/include_platform/android/activity_manager.h
@@ -115,8 +115,6 @@
AACTIVITYMANAGER_IMPORTANCE_GONE = 1000,
};
-#if __ANDROID_API__ >= 31
-
/**
* Adds a UidImportanceListener to the ActivityManager.
*
@@ -169,8 +167,6 @@
*/
int32_t AActivityManager_getUidImportance(uid_t uid) __INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
__END_DECLS
#endif // __AACTIVITYMANAGER_H__
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 15b473c..3751564 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -22,22 +22,20 @@
"-Wunreachable-code",
],
- // our source files
- //
srcs: [
- "aassetstreamadaptor.cpp",
- "bitmap.cpp",
"imagedecoder.cpp",
],
shared_libs: [
- "libandroid",
"libandroid_runtime",
"libhwui",
"liblog",
],
- header_libs: [ "libhwui_internal_headers" ],
+ header_libs: [
+ "libhwui_internal_headers",
+ "jni_headers",
+ ],
static_libs: ["libarect"],
@@ -48,7 +46,24 @@
ldflags: ["-Wl,--hash-style=both"],
},
},
- version_script: "libjnigraphics.map.txt",
+ host_supported: true,
+ target: {
+ android: {
+ srcs: [
+ "aassetstreamadaptor.cpp",
+ "bitmap.cpp",
+ ],
+ shared_libs: [
+ "libandroid",
+ ],
+ version_script: "libjnigraphics.map.txt",
+ },
+ host: {
+ header_libs: [
+ "libnativewindow_headers",
+ ],
+ },
+ },
}
// The headers module is in frameworks/native/Android.bp.
@@ -58,3 +73,30 @@
first_version: "9",
unversioned_until: "current",
}
+
+cc_fuzz {
+ name: "imagedecoder_fuzzer",
+ srcs: ["fuzz_imagedecoder.cpp"],
+ header_libs: ["jni_headers"],
+ shared_libs: [
+ "libbinder",
+ "libjnigraphics",
+ "libutils",
+ ],
+ static_libs: ["libarect"],
+ fuzz_config: {
+ cc: ["scroggo@google.com"],
+ asan_options: [
+ "detect_odr_violation=1",
+ ],
+ hwasan_options: [
+ // Image decoders may attempt to allocate a large amount of memory
+ // (especially if the encoded image is large). This doesn't
+ // necessarily mean there is a bug. Set allocator_may_return_null=1
+ // for hwasan so the fuzzer can continue running.
+ "allocator_may_return_null = 1",
+ ],
+ },
+ corpus: ["corpus/*"],
+ host_supported: true,
+}
diff --git a/native/graphics/jni/corpus/baseline_jpeg.jpg b/native/graphics/jni/corpus/baseline_jpeg.jpg
new file mode 100644
index 0000000..ed5251c
--- /dev/null
+++ b/native/graphics/jni/corpus/baseline_jpeg.jpg
Binary files differ
diff --git a/native/graphics/jni/corpus/color_wheel.ico b/native/graphics/jni/corpus/color_wheel.ico
new file mode 100644
index 0000000..fdfa381c
--- /dev/null
+++ b/native/graphics/jni/corpus/color_wheel.ico
Binary files differ
diff --git a/native/graphics/jni/corpus/gif_test.gif b/native/graphics/jni/corpus/gif_test.gif
new file mode 100644
index 0000000..d1c2815
--- /dev/null
+++ b/native/graphics/jni/corpus/gif_test.gif
Binary files differ
diff --git a/native/graphics/jni/corpus/google_chrome.ico b/native/graphics/jni/corpus/google_chrome.ico
new file mode 100644
index 0000000..7af91ee
--- /dev/null
+++ b/native/graphics/jni/corpus/google_chrome.ico
Binary files differ
diff --git a/native/graphics/jni/corpus/heifwriter_input.heic b/native/graphics/jni/corpus/heifwriter_input.heic
new file mode 100644
index 0000000..1f4573a
--- /dev/null
+++ b/native/graphics/jni/corpus/heifwriter_input.heic
Binary files differ
diff --git a/native/graphics/jni/corpus/mandrill.wbmp b/native/graphics/jni/corpus/mandrill.wbmp
new file mode 100644
index 0000000..ac84598
--- /dev/null
+++ b/native/graphics/jni/corpus/mandrill.wbmp
Binary files differ
diff --git a/native/graphics/jni/corpus/png_test.png b/native/graphics/jni/corpus/png_test.png
new file mode 100644
index 0000000..5230051
--- /dev/null
+++ b/native/graphics/jni/corpus/png_test.png
Binary files differ
diff --git a/native/graphics/jni/corpus/progressive_jpeg.jpg b/native/graphics/jni/corpus/progressive_jpeg.jpg
new file mode 100644
index 0000000..6b58be4
--- /dev/null
+++ b/native/graphics/jni/corpus/progressive_jpeg.jpg
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_1mp.dng b/native/graphics/jni/corpus/sample_1mp.dng
new file mode 100644
index 0000000..c1c1078
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_1mp.dng
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_arw.arw b/native/graphics/jni/corpus/sample_arw.arw
new file mode 100644
index 0000000..2b05931
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_arw.arw
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_cr2.cr2 b/native/graphics/jni/corpus/sample_cr2.cr2
new file mode 100644
index 0000000..adbbc97
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_cr2.cr2
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_nef.nef b/native/graphics/jni/corpus/sample_nef.nef
new file mode 100644
index 0000000..282614b
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_nef.nef
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_nrw.nrw b/native/graphics/jni/corpus/sample_nrw.nrw
new file mode 100644
index 0000000..f91eff4
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_nrw.nrw
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_orf.orf b/native/graphics/jni/corpus/sample_orf.orf
new file mode 100644
index 0000000..60eea3a
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_orf.orf
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_pef.pef b/native/graphics/jni/corpus/sample_pef.pef
new file mode 100644
index 0000000..d4f6d48
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_pef.pef
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_raf.raf b/native/graphics/jni/corpus/sample_raf.raf
new file mode 100644
index 0000000..edb23b4
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_raf.raf
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_rw2.rw2 b/native/graphics/jni/corpus/sample_rw2.rw2
new file mode 100644
index 0000000..9db5b45
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_rw2.rw2
Binary files differ
diff --git a/native/graphics/jni/corpus/sample_srw.srw b/native/graphics/jni/corpus/sample_srw.srw
new file mode 100644
index 0000000..cb9b033
--- /dev/null
+++ b/native/graphics/jni/corpus/sample_srw.srw
Binary files differ
diff --git a/native/graphics/jni/corpus/webp-color-profile-lossless.webp b/native/graphics/jni/corpus/webp-color-profile-lossless.webp
new file mode 100644
index 0000000..4fd63d5
--- /dev/null
+++ b/native/graphics/jni/corpus/webp-color-profile-lossless.webp
Binary files differ
diff --git a/native/graphics/jni/corpus/webp_animated.webp b/native/graphics/jni/corpus/webp_animated.webp
new file mode 100644
index 0000000..35a8dfc
--- /dev/null
+++ b/native/graphics/jni/corpus/webp_animated.webp
Binary files differ
diff --git a/native/graphics/jni/corpus/webp_test.webp b/native/graphics/jni/corpus/webp_test.webp
new file mode 100644
index 0000000..7b1009f
--- /dev/null
+++ b/native/graphics/jni/corpus/webp_test.webp
Binary files differ
diff --git a/native/graphics/jni/fuzz_imagedecoder.cpp b/native/graphics/jni/fuzz_imagedecoder.cpp
new file mode 100644
index 0000000..015aca7
--- /dev/null
+++ b/native/graphics/jni/fuzz_imagedecoder.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/imagedecoder.h>
+
+#include <binder/IPCThreadState.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <cstdlib>
+#include <memory>
+
+struct DecoderDeleter {
+ void operator()(AImageDecoder* decoder) const { AImageDecoder_delete(decoder); }
+};
+
+using DecoderPointer = std::unique_ptr<AImageDecoder, DecoderDeleter>;
+
+static DecoderPointer makeDecoder(const uint8_t* data, size_t size) {
+ AImageDecoder* decoder = nullptr;
+ int result = AImageDecoder_createFromBuffer(data, size, &decoder);
+ if (result != ANDROID_IMAGE_DECODER_SUCCESS) {
+ // This was not a valid image.
+ return nullptr;
+ }
+ return DecoderPointer(decoder);
+}
+
+struct PixelFreer {
+ void operator()(void* pixels) const { std::free(pixels); }
+};
+
+using PixelPointer = std::unique_ptr<void, PixelFreer>;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // Without this call, decoding HEIF may time out on binder IPC calls.
+ android::ProcessState::self()->startThreadPool();
+
+ DecoderPointer decoder = makeDecoder(data, size);
+ if (!decoder) {
+ return 0;
+ }
+
+ const AImageDecoderHeaderInfo* info = AImageDecoder_getHeaderInfo(decoder.get());
+ int32_t width = AImageDecoderHeaderInfo_getWidth(info);
+ int32_t height = AImageDecoderHeaderInfo_getHeight(info);
+
+ // Set an arbitrary limit on the size of an image. The fuzzer runs with a
+ // limited amount of memory, and keeping this allocation small allows the
+ // fuzzer to continue running to try to find more serious problems. This
+ // size is large enough to hold a photo taken by a current gen phone.
+ constexpr int32_t kMaxDimension = 5000;
+ if (width > kMaxDimension || height > kMaxDimension) {
+ return 0;
+ }
+
+ size_t stride = AImageDecoder_getMinimumStride(decoder.get());
+ size_t pixelSize = height * stride;
+ auto pixels = PixelPointer(std::malloc(pixelSize));
+ if (!pixels.get()) {
+ return 0;
+ }
+
+ while (true) {
+ int result = AImageDecoder_decodeImage(decoder.get(), pixels.get(), stride, pixelSize);
+ if (result != ANDROID_IMAGE_DECODER_SUCCESS) break;
+
+ result = AImageDecoder_advanceFrame(decoder.get());
+ if (result != ANDROID_IMAGE_DECODER_SUCCESS) break;
+ }
+ return 0;
+}
diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index 0f61907..eab5f41 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -121,8 +121,12 @@
}
*outDecoder = nullptr;
+#ifdef __ANDROID__
auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
return createFromStream(std::move(stream), outDecoder);
+#else
+ return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
+#endif
}
static bool isSeekable(int descriptor) {
@@ -535,3 +539,9 @@
return ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER;
}
}
+
+void AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder* decoder, bool handle) {
+ if (decoder) {
+ toDecoder(decoder)->setHandleRestorePrevious(handle);
+ }
+}
diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt
index d8c3cef..e0df794 100644
--- a/native/graphics/jni/libjnigraphics.map.txt
+++ b/native/graphics/jni/libjnigraphics.map.txt
@@ -19,6 +19,7 @@
AImageDecoder_advanceFrame; # introduced=31
AImageDecoder_rewind; # introduced=31
AImageDecoder_getFrameInfo; # introduced = 31
+ AImageDecoder_setInternallyHandleDisposePrevious; # introduced = 31
AImageDecoderHeaderInfo_getWidth; # introduced=30
AImageDecoderHeaderInfo_getHeight; # introduced=30
AImageDecoderHeaderInfo_getMimeType; # introduced=30
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index cb062a6..6e49b05 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -171,7 +171,7 @@
portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
| Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, portalIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
Notification notification = getNotification(context, R.string.portal_notification_id,
R.string.portal_notification_detail, pendingIntent);
try {
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
index 8fc3531..cdf4851 100644
--- a/packages/CompanionDeviceManager/res/values-af/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Metgeseltoestel-bestuurder"</string>
<string name="chooser_title" msgid="2262294130493605839">"Kies \'n <xliff:g id="PROFILE_NAME">%1$s</xliff:g> om deur <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> bestuur te word"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"toestel"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"horlosie"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Stel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> om jou <xliff:g id="PROFILE_NAME">%2$s</xliff:g> te bestuur – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Jy het <xliff:g id="APP_NAME_0">%1$s</xliff:g> nodig om jou <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> te bestuur. <xliff:g id="APP_NAME2">%3$s</xliff:g> sal toegang hê tot <xliff:g id="PERMISSIONS">%4$s</xliff:g> terwyl die <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> gekoppel is."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Jy het <xliff:g id="APP_NAME">%1$s</xliff:g> nodig om jou <xliff:g id="PROFILE_NAME">%2$s</xliff:g> te bestuur. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nee, dankie"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
index ff31454..a03ea0df 100644
--- a/packages/CompanionDeviceManager/res/values-am/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"አጃቢ የመሣሪያ አስተዳዳሪ"</string>
<string name="chooser_title" msgid="2262294130493605839">"በ<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> የሚተዳደር <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ይምረጡ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"መሣሪያ"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ሰዓት"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> የእርስዎን <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> እንዲያስተዳድር ያቀናብሩት"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> የእርስዎን <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ለማስተዳደር ያስፈልጋል። <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ተገናኝቶ ሳለ <xliff:g id="APP_NAME2">%3$s</xliff:g> የ<xliff:g id="PERMISSIONS">%4$s</xliff:g> መዳረሻን ያገኛል።"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> የእርስዎን <xliff:g id="PROFILE_NAME">%2$s</xliff:g> ለማስተዳደር ያስፈልጋል። <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"አዎ"</string>
<string name="consent_no" msgid="1335543792857823917">"አይ፣ አመሰግናለሁ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
index aedf0f3..970c46b 100644
--- a/packages/CompanionDeviceManager/res/values-ar/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"تطبيق \"مدير الجهاز المصاحب\""</string>
<string name="chooser_title" msgid="2262294130493605839">"اختَر <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ليديره تطبيق <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"جهاز"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ساعة"</string>
<string name="confirmation_title" msgid="4751119145078041732">"اضبط <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> لإدارة <xliff:g id="PROFILE_NAME">%2$s</xliff:g> على <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"يجب توفّر تطبيق <xliff:g id="APP_NAME_0">%1$s</xliff:g> لإدارة <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. سيتمكن تطبيق <xliff:g id="APP_NAME2">%3$s</xliff:g> من الوصول إلى <xliff:g id="PERMISSIONS">%4$s</xliff:g> عندما يكون <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> مرتبطًا."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"يجب توفّر تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> لإدارة <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"نعم"</string>
<string name="consent_no" msgid="1335543792857823917">"لا، شكرًا"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
index f0c3ee8..477844c 100644
--- a/packages/CompanionDeviceManager/res/values-as/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"কম্পেনিয়ন ডিভাইচ মেনেজাৰ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>এ পৰিচালনা কৰিব লগা এটা <xliff:g id="PROFILE_NAME">%1$s</xliff:g> বাছনি কৰক"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইচ"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ঘড়ী"</string>
<string name="confirmation_title" msgid="4751119145078041732">"আপোনাৰ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> পৰিচালনা কৰিবলৈ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ছেট কৰক - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"আপোনাৰ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> পৰিচালনা কৰিবলৈ <xliff:g id="APP_NAME_0">%1$s</xliff:g>ৰ আৱশ্যক। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>ৰ সৈতে সংযোগ কৰিলে <xliff:g id="APP_NAME2">%3$s</xliff:g>এ <xliff:g id="PERMISSIONS">%4$s</xliff:g>লৈ এক্সেছ পাব।"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"আপোনাৰ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> পৰিচালনা কৰিবলৈ <xliff:g id="APP_NAME">%1$s</xliff:g>ৰ আৱশ্যক। <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"হয়"</string>
<string name="consent_no" msgid="1335543792857823917">"নালাগে, ধন্যবাদ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
index 64bea4d..f10c639 100644
--- a/packages/CompanionDeviceManager/res/values-az/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Kompanyon Cihaz Meneceri"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tərəfindən idarə ediləcək <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"izləyin"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> profilinizin <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tərəfindən idarə olunmasını ayarlayın - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> profilinizi idarə etmək üçün <xliff:g id="APP_NAME_0">%1$s</xliff:g> tələb olunur. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> qoşulu olduqda <xliff:g id="APP_NAME2">%3$s</xliff:g> <xliff:g id="PERMISSIONS">%4$s</xliff:g> bölməsinə giriş əldə edəcək."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> profilinizi idarə etmək üçün <xliff:g id="APP_NAME">%1$s</xliff:g> tələb olunur. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Bəli"</string>
<string name="consent_no" msgid="1335543792857823917">"Xeyr, çox sağolun"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
index 3f06722..e8542f3 100644
--- a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Menadžer pridruženog uređaja"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Podesite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja profilom <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> je neophodna za upravljanje profilom <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> će dobiti pristup dozvolama za <xliff:g id="PERMISSIONS">%4$s</xliff:g> dok je <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> povezan."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je neophodna za upravljanje profilom <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, hvala"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
index 25e235c..13be6f2 100644
--- a/packages/CompanionDeviceManager/res/values-be/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Менеджар спадарожнай прылады"</string>
<string name="chooser_title" msgid="2262294130493605839">"Выберыце прыладу (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), якой будзе кіраваць праграма <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"прылада"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"гадзіннік"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Дазвольце праграме <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> кіраваць прыладай \"<xliff:g id="PROFILE_NAME">%2$s</xliff:g>\" – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Для кіравання прыладай \"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>\" патрабуецца праграма \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\". Калі прылада \"<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>\" будзе падключана, <xliff:g id="APP_NAME2">%3$s</xliff:g> атрымае наступныя дазволы: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Для кіравання прыладай \"<xliff:g id="PROFILE_NAME">%2$s</xliff:g>\" патрабуецца праграма \"<xliff:g id="APP_NAME">%1$s</xliff:g>\". <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Так"</string>
<string name="consent_no" msgid="1335543792857823917">"Не, дзякуй"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
index 264ce27..3bda5e6 100644
--- a/packages/CompanionDeviceManager/res/values-bg/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Изберете устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), което да се управлява от <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Задайте <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да управлява устройството ви (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"За управление на <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> се изисква <xliff:g id="APP_NAME_0">%1$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> ще получи достъп до <xliff:g id="PERMISSIONS">%4$s</xliff:g>, докато устройството (<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>) е свързано."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"За управление на <xliff:g id="PROFILE_NAME">%2$s</xliff:g> се изисква <xliff:g id="APP_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Да"</string>
<string name="consent_no" msgid="1335543792857823917">"Не, благодаря"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
index 65f92c9..d3bc515 100644
--- a/packages/CompanionDeviceManager/res/values-bn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> বেছে নিন যেটি <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ম্যানেজ করবে"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ডিভাইস"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"দেখুন"</string>
<string name="confirmation_title" msgid="4751119145078041732">"আপনার <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ম্যানেজ করার জন্য <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> সেট করুন"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>-কে আপনার <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>.ম্যানেজ করতে দিতে হবে। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> কানেক্ট করা হলে <xliff:g id="APP_NAME2">%3$s</xliff:g> <xliff:g id="PERMISSIONS">%4$s</xliff:g> অ্যাক্সেস করতে পারবে।"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g>-কে আপনার <xliff:g id="PROFILE_NAME">%2$s</xliff:g>.ম্যানেজ করতে দিতে হবে। <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"হ্যাঁ"</string>
<string name="consent_no" msgid="1335543792857823917">"না থাক"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
index f8e24b7..905b306 100644
--- a/packages/CompanionDeviceManager/res/values-bs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Prateći upravitelj uređaja"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite uređaj <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"sat"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Postavite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja vašim uređajem <xliff:g id="PROFILE_NAME">%2$s</xliff:g> — <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Potrebna je aplikacija <xliff:g id="APP_NAME_0">%1$s</xliff:g> za upravljanje uređajem <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME2">%3$s</xliff:g> će dobiti pristup uslugama <xliff:g id="PERMISSIONS">%4$s</xliff:g> dok je uređaj <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> povezan."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Potrebna je aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> za upravljanje uređajem <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, hvala"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index ae8ca9f..86dc694 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gestor de dispositius complementaris"</string>
<string name="chooser_title" msgid="2262294130493605839">"Tria un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> perquè el gestioni <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositiu"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"rellotge"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Defineix que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gestioni el teu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Cal <xliff:g id="APP_NAME_0">%1$s</xliff:g> per gestionar el teu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> tindrà accés als permisos <xliff:g id="PERMISSIONS">%4$s</xliff:g> mentre el <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> estigui connectat."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"L\'aplicació <xliff:g id="APP_NAME">%1$s</xliff:g> és necessària per gestionar el teu <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Sí"</string>
<string name="consent_no" msgid="1335543792857823917">"No, gràcies"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
index 675bd29..389ccd0 100644
--- a/packages/CompanionDeviceManager/res/values-cs/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Správce doprovodných zařízení"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vyberte zařízení <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, které chcete spravovat pomocí aplikace <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"zařízení"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Nastavit aplikaci <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ke správě tohoto zařízení: <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Ke správě zařízení <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> je potřeba aplikace <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Dokud bude zařízení <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> připojeno, bude mít aplikace <xliff:g id="APP_NAME2">%3$s</xliff:g> přístup k těmto oprávněním: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Ke správě profilu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> je potřeba aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ano"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, díky"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
index a6720fc..5a31f9b 100644
--- a/packages/CompanionDeviceManager/res/values-da/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Medfølgende enhedshåndtering"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vælg den enhed (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), som skal administreres af <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhed"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ur"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Angiv <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> til administration af: <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er nødvendig for at administrere: <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> får adgang til <xliff:g id="PERMISSIONS">%4$s</xliff:g>, mens <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> er forbundet."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> er nødvendig for at administrere: <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nej tak"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
index eb2631f..ead68e3 100644
--- a/packages/CompanionDeviceManager/res/values-de/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Begleitgerät-Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Gerät (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) auswählen, das von <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> verwaltet werden soll"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"Gerät"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> zum Verwalten deines Geräts (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) festlegen – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ist erforderlich, um dein Gerät (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>) zu verwalten. <xliff:g id="APP_NAME2">%3$s</xliff:g> erhält Zugriff auf <xliff:g id="PERMISSIONS">%4$s</xliff:g>, während eine Verbindung mit <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> besteht."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nein danke"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
index cb31866..60de2ff 100644
--- a/packages/CompanionDeviceManager/res/values-el/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Διαχείριση συνοδευτικής εφαρμογής"</string>
<string name="chooser_title" msgid="2262294130493605839">"Επιλέξτε ένα προφίλ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> για διαχείριση από την εφαρμογή <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"συσκευή"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ρολόι"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Ορίστε μια εφαρμογή <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> για διαχείριση του προφίλ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Η εφαρμογή <xliff:g id="APP_NAME_0">%1$s</xliff:g> απαιτείται για τη διαχείριση του προφίλ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Η εφαρμογή <xliff:g id="APP_NAME2">%3$s</xliff:g> θα έχει πρόσβαση στις άδειες <xliff:g id="PERMISSIONS">%4$s</xliff:g> ενώ είναι συνδεδεμένο το προφίλ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> απαιτείται για τη διαχείριση του προφίλ <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ναι"</string>
<string name="consent_no" msgid="1335543792857823917">"Όχι, ευχαριστώ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
index a30c199..2fed1ae 100644
--- a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No, thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
index a30c199..2fed1ae 100644
--- a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No, thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
index a30c199..2fed1ae 100644
--- a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No, thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
index a30c199..2fed1ae 100644
--- a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No, thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
index ea39d0a..f3c4b1d 100644
--- a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choose a <xliff:g id="PROFILE_NAME">%1$s</xliff:g> to be managed by <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"watch"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Set <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> will get access to <xliff:g id="PERMISSIONS">%4$s</xliff:g> while the <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is connected."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> is needed to manage your <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"No thanks"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
index 63097dc..4fbb57e 100644
--- a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Administrador de dispositivo complementario"</string>
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para que <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> lo administre"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Configura <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> para administrar <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Se requiere <xliff:g id="APP_NAME_0">%1$s</xliff:g> para administrar tu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> accederá a <xliff:g id="PERMISSIONS">%4$s</xliff:g> mientras tu <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> esté conectado."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Se requiere <xliff:g id="APP_NAME">%1$s</xliff:g> para administrar tu <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Sí"</string>
<string name="consent_no" msgid="1335543792857823917">"No, gracias"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
index 784c30d..5ca9305 100644
--- a/packages/CompanionDeviceManager/res/values-es/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos complementario"</string>
<string name="chooser_title" msgid="2262294130493605839">"Elige un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para gestionarlo con <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"reloj"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Haz que <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> gestione tu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Se necesita <xliff:g id="APP_NAME_0">%1$s</xliff:g> para gestionar tu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Mientras tu <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> esté conectado, <xliff:g id="APP_NAME2">%3$s</xliff:g> tendrá acceso a lo siguiente: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Se necesita <xliff:g id="APP_NAME">%1$s</xliff:g> para gestionar tu <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Sí"</string>
<string name="consent_no" msgid="1335543792857823917">"No, gracias"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
index b505870..357f052 100644
--- a/packages/CompanionDeviceManager/res/values-et/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Kaasseadme haldur"</string>
<string name="chooser_title" msgid="2262294130493605839">"Valige seade <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, mida haldab rakendus <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"seade"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"käekell"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Määrake rakendus <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> haldama teie seadet <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> on vajalik teie seadme <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> haldamiseks. <xliff:g id="APP_NAME2">%3$s</xliff:g> saab juurdepääsuload (<xliff:g id="PERMISSIONS">%4$s</xliff:g>), kui seade <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> on ühendatud."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> on vajalik teie seadme <xliff:g id="PROFILE_NAME">%2$s</xliff:g> haldamiseks. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Jah"</string>
<string name="consent_no" msgid="1335543792857823917">"Tänan, ei"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
index 826556d..14c7154 100644
--- a/packages/CompanionDeviceManager/res/values-eu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gailu osagarriaren kudeatzailea"</string>
<string name="chooser_title" msgid="2262294130493605839">"Aukeratu <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> aplikazioak kudeatu beharreko <xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"gailua"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"erlojua"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Konfiguratu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>) kudea dezan"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> erabili behar duzu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> kudeatzeko. <xliff:g id="APP_NAME2">%3$s</xliff:g> aplikazioak <xliff:g id="PERMISSIONS">%4$s</xliff:g> atzitu ahalko ditu <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> konektatuta dagoen bitartean."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> erabili behar duzu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> kudeatzeko. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Bai"</string>
<string name="consent_no" msgid="1335543792857823917">"Ez"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
index 66eafc3..6bb9620 100644
--- a/packages/CompanionDeviceManager/res/values-fa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"مدیر دستگاه مرتبط"</string>
<string name="chooser_title" msgid="2262294130493605839">"انتخاب <xliff:g id="PROFILE_NAME">%1$s</xliff:g> برای مدیریت کردن با <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"دستگاه"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ساعت"</string>
<string name="confirmation_title" msgid="4751119145078041732">"تنظیم <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> برای مدیریت کردن <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"برای مدیریت کردن <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> به <xliff:g id="APP_NAME_0">%1$s</xliff:g> نیاز دارید. وقتی <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> متصل باشد، <xliff:g id="APP_NAME2">%3$s</xliff:g> به <xliff:g id="PERMISSIONS">%4$s</xliff:g> دسترسی پیدا خواهد کرد."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"برای مدیریت کردن <xliff:g id="PROFILE_NAME">%2$s</xliff:g> به <xliff:g id="APP_NAME">%1$s</xliff:g> نیاز دارید. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"بله"</string>
<string name="consent_no" msgid="1335543792857823917">"نه متشکرم"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
index d4a20d9..5a9c1cd 100644
--- a/packages/CompanionDeviceManager/res/values-fi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Valitse <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, jota <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> hallinnoi"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"laite"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"kello"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Aseta <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> profiilin (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) hallinnoijaksi – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> tarvitaan profiilin (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>) hallinnointiin. <xliff:g id="APP_NAME2">%3$s</xliff:g> saa käyttöluvat (<xliff:g id="PERMISSIONS">%4$s</xliff:g>), kun <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> on yhdistetty."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> tarvitaan profiilin (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) hallinnointiin. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Kyllä"</string>
<string name="consent_no" msgid="1335543792857823917">"Ei kiitos"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
index e91ccf4..b31babd 100644
--- a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareil compagnon"</string>
<string name="chooser_title" msgid="2262294130493605839">"Choisissez un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Utiliser <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pour gérer votre <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"L\'application <xliff:g id="APP_NAME_0">%1$s</xliff:g> est requise pour gérer votre <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> aura accès à <xliff:g id="PERMISSIONS">%4$s</xliff:g> lorsque <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> est connecté."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"L\'application <xliff:g id="APP_NAME">%1$s</xliff:g> est requise pour gérer votre <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Oui"</string>
<string name="consent_no" msgid="1335543792857823917">"Non merci"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
index 756727a..08c93a2c 100644
--- a/packages/CompanionDeviceManager/res/values-fr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareils associés"</string>
<string name="chooser_title" msgid="2262294130493605839">"Sélectionner le/la <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qui sera géré(e) par <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"appareil"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"montre"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Définir <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pour la gestion de votre <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> est requis pour gérer votre <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> aura accès aux <xliff:g id="PERMISSIONS">%4$s</xliff:g> lorsque le/la <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> sera connecté(e)."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> est requis pour gérer votre <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Oui"</string>
<string name="consent_no" msgid="1335543792857823917">"Non, merci"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
index 7849e42..c95b90e 100644
--- a/packages/CompanionDeviceManager/res/values-gl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Xestor de dispositivos complementarios"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolle un perfil (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) para que o xestione a aplicación <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"reloxo"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Define a aplicación <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> para a xestión do teu perfil (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>): <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Necesítase a aplicación <xliff:g id="APP_NAME_0">%1$s</xliff:g> para xestionar o teu perfil (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>). <xliff:g id="APP_NAME2">%3$s</xliff:g> terá acceso a varios permisos (<xliff:g id="PERMISSIONS">%4$s</xliff:g>) mentres o perfil (<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>) estea conectado."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Necesítase a aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> para xestionar o teu perfil (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>). <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Si"</string>
<string name="consent_no" msgid="1335543792857823917">"Non, grazas"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
index 1f1edd1..e99a3cd 100644
--- a/packages/CompanionDeviceManager/res/values-gu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"કમ્પેનિયન ડિવાઇસ મેનેજર"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> દ્વારા મેનેજ કરવા માટે કોઈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> પસંદ કરો"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ડિવાઇસ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"તમારા <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>ને મેનેજ કરવા માટે <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> સેટ કરો"</string>
- <string name="profile_summary" msgid="3167701603666642104">"તમારા <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>ને મેનેજ કરવા માટે <xliff:g id="APP_NAME_0">%1$s</xliff:g> જરૂરી છે. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> જ્યારે કનેક્ટેડ હોય ત્યારે <xliff:g id="APP_NAME2">%3$s</xliff:g>ને <xliff:g id="PERMISSIONS">%4$s</xliff:g>નો ઍક્સેસ મળશે."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"હા"</string>
<string name="consent_no" msgid="1335543792857823917">"ના, આભાર"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
index 6e280b5..ac95cc6 100644
--- a/packages/CompanionDeviceManager/res/values-hi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string>
<string name="chooser_title" msgid="2262294130493605839">"कोई <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चुनें, ताकि उसे <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> की मदद से प्रबंधित किया जा सके"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिवाइस"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"स्मार्टवॉच"</string>
<string name="confirmation_title" msgid="4751119145078041732">"अपने <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> को प्रबंधित करने के लिए, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को सेट करें"</string>
- <string name="profile_summary" msgid="3167701603666642104">"आपके <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> को प्रबंधित करने के लिए, <xliff:g id="APP_NAME_0">%1$s</xliff:g> की ज़रूरत है. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> के कनेक्ट होने पर, <xliff:g id="APP_NAME2">%3$s</xliff:g> को <xliff:g id="PERMISSIONS">%4$s</xliff:g> का ऐक्सेस मिल जाएगा."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"आपके <xliff:g id="PROFILE_NAME">%2$s</xliff:g> को प्रबंधित करने के लिए, <xliff:g id="APP_NAME">%1$s</xliff:g> की ज़रूरत है. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"हां"</string>
<string name="consent_no" msgid="1335543792857823917">"नहीं, रहने दें"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
index beacbfd..df8451f 100644
--- a/packages/CompanionDeviceManager/res/values-hr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Odaberite profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kojim će upravljati aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"uređaj"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"satom"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Postavite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> da upravlja vašim profilom <xliff:g id="PROFILE_NAME">%2$s</xliff:g> –- <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Potrebna je <xliff:g id="APP_NAME_0">%1$s</xliff:g> za upravljanje vašim profilom <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Aplikacija <xliff:g id="APP_NAME2">%3$s</xliff:g> dobit će pristup dopuštenju za <xliff:g id="PERMISSIONS">%4$s</xliff:g> dok je povezan profil <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> potrebna je za upravljanje vašim <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, hvala"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
index cd29006..ff1c6c5 100644
--- a/packages/CompanionDeviceManager/res/values-hu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Társeszközök kezelője"</string>
<string name="chooser_title" msgid="2262294130493605839">"A(z) <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> alkalmazással kezelni kívánt <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiválasztása"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"eszköz"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"óra"</string>
<string name="confirmation_title" msgid="4751119145078041732">"A(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazás beállítása a(z) <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>) kezelésére"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Szükség van a(z) <xliff:g id="APP_NAME_0">%1$s</xliff:g> alkalmazásra a(z) <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> kezeléséhez. Amíg csatlakoztatva van a(z) <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>, a(z) <xliff:g id="APP_NAME2">%3$s</xliff:g> hozzáférést kap a következőkhöz: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Szükség van a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásra a(z) <xliff:g id="PROFILE_NAME">%2$s</xliff:g> kezeléséhez. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Igen"</string>
<string name="consent_no" msgid="1335543792857823917">"Nem"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
index b0037aa..194223d 100644
--- a/packages/CompanionDeviceManager/res/values-hy/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Ընտրեք <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ը, որը պետք է կառավարվի <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> հավելվածի կողմից"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"սարք"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ժամացույց"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Ընտրեք <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածը որպես <xliff:g id="PROFILE_NAME">%2$s</xliff:g>ի կառավարիչ․ <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Ձեր <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>ը կառավարելու համար անհրաժեշտ է <xliff:g id="APP_NAME_0">%1$s</xliff:g> հավելվածը։ Երբ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>ը միացված լինի, <xliff:g id="APP_NAME2">%3$s</xliff:g> հավելվածին հասանելի կլինեն՝ <xliff:g id="PERMISSIONS">%4$s</xliff:g>։"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Ձեր <xliff:g id="PROFILE_NAME">%2$s</xliff:g>ը կառավարելու համար անհրաժեշտ է <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածը։ <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Այո"</string>
<string name="consent_no" msgid="1335543792857823917">"Ոչ, շնորհակալություն"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
index cc05490..58bf3cb 100644
--- a/packages/CompanionDeviceManager/res/values-in/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Pengelola Perangkat Pendamping"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk dikelola oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"perangkat"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"smartwatch"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Tetapkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengelola <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> diperlukan untuk mengelola <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> akan mendapatkan akses ke <xliff:g id="PERMISSIONS">%4$s</xliff:g> saat <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> terhubung."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Perlu <xliff:g id="APP_NAME">%1$s</xliff:g> untuk mengelola <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ya"</string>
<string name="consent_no" msgid="1335543792857823917">"Tidak"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
index d3ada74..cc5b989 100644
--- a/packages/CompanionDeviceManager/res/values-is/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Stjórnun fylgdartækja"</string>
<string name="chooser_title" msgid="2262294130493605839">"Velja <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sem <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> á að stjórna"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"tæki"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"úr"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Veita <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> stjórn á <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> er krafist til að stjórna <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> fær aðgang að <xliff:g id="PERMISSIONS">%4$s</xliff:g> þegar <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> er tengt."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> er krafist til að stjórna <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Já"</string>
<string name="consent_no" msgid="1335543792857823917">"Nei, takk"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
index 2632509..4cbefd8 100644
--- a/packages/CompanionDeviceManager/res/values-it/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gestione dispositivi companion"</string>
<string name="chooser_title" msgid="2262294130493605839">"Scegli un <xliff:g id="PROFILE_NAME">%1$s</xliff:g> che sia gestito da <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"orologio"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Configura <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> per gestire il tuo <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"È richiesta l\'app <xliff:g id="APP_NAME_0">%1$s</xliff:g> per gestire il tuo <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> avrà accesso a <xliff:g id="PERMISSIONS">%4$s</xliff:g> quando <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> è connesso."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"È richiesta l\'app <xliff:g id="APP_NAME">%1$s</xliff:g> per gestire il tuo <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Sì"</string>
<string name="consent_no" msgid="1335543792857823917">"No, grazie"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
index ae9d6f4..33950eb 100644
--- a/packages/CompanionDeviceManager/res/values-iw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ניהול מכשיר מותאם"</string>
<string name="chooser_title" msgid="2262294130493605839">"בחירה של <xliff:g id="PROFILE_NAME">%1$s</xliff:g> לניהול באמצעות <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"מכשיר"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"הגדרה של <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> לניהול <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"האפליקציה <xliff:g id="APP_NAME_0">%1$s</xliff:g> נדרשת לניהול של <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. האפליקציה <xliff:g id="APP_NAME2">%3$s</xliff:g> תקבל גישה אל <xliff:g id="PERMISSIONS">%4$s</xliff:g> כאשר <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> מחובר."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"כן"</string>
<string name="consent_no" msgid="1335543792857823917">"לא תודה"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
index 3fb0140..b695d9d 100644
--- a/packages/CompanionDeviceManager/res/values-ja/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"コンパニオン デバイス マネージャ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> の管理対象となる <xliff:g id="PROFILE_NAME">%1$s</xliff:g> の選択"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"デバイス"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ウォッチ"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> で <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> を管理するよう設定する"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> を管理するために <xliff:g id="APP_NAME_0">%1$s</xliff:g> が必要です。<xliff:g id="PROFILE_NAME2">%5$s</xliff:g> の接続中に、<xliff:g id="APP_NAME2">%3$s</xliff:g> が <xliff:g id="PERMISSIONS">%4$s</xliff:g> にアクセスします。"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> を管理するために <xliff:g id="APP_NAME">%1$s</xliff:g> が必要です。<xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"はい"</string>
<string name="consent_no" msgid="1335543792857823917">"いいえ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
index 5b36106..300c94f 100644
--- a/packages/CompanionDeviceManager/res/values-ka/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"კომპანიონი მოწყობილობების მენეჯერი"</string>
<string name="chooser_title" msgid="2262294130493605839">"აირჩიეთ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, რომელიც უნდა მართოს <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-მა"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"მოწყობილობა"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"საათი"</string>
<string name="confirmation_title" msgid="4751119145078041732">"დააყენეთ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>, რომ მართოს თქვენი <xliff:g id="PROFILE_NAME">%2$s</xliff:g> — <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"თქვენი <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>-ის სამართავად საჭიროა <xliff:g id="APP_NAME_0">%1$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> მიიღებს წვდომას <xliff:g id="PERMISSIONS">%4$s</xliff:g>-ზე, სანამ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> დაკავშირებული იქნება."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"თქვენი <xliff:g id="PROFILE_NAME">%2$s</xliff:g>-ის სამართავად საჭიროა <xliff:g id="APP_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"დიახ"</string>
<string name="consent_no" msgid="1335543792857823917">"არა, გმადლობთ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
index 6ff3f83..94d6c3e 100644
--- a/packages/CompanionDeviceManager/res/values-kk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> арқылы басқарылатын <xliff:g id="PROFILE_NAME">%1$s</xliff:g> құрылғысын таңдаңыз"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"құрылғы"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"сағат"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасына <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>) құрылғысын басқаруға рұқсат беру"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> құрылғысын басқару үшін <xliff:g id="APP_NAME_0">%1$s</xliff:g> қолданбасы керек. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> құрылғысы жалғанған кезде<xliff:g id="APP_NAME2">%3$s</xliff:g> қолданбасы мына параметрлерді пайдалана алады: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> құрылғысын басқару үшін <xliff:g id="APP_NAME">%1$s</xliff:g> қолданбасы керек. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Иә"</string>
<string name="consent_no" msgid="1335543792857823917">"Жоқ, рақмет"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
index cdcebad..db13fe7 100644
--- a/packages/CompanionDeviceManager/res/values-km/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"កម្មវិធីគ្រប់គ្រងឧបករណ៍ដៃគូ"</string>
<string name="chooser_title" msgid="2262294130493605839">"ជ្រើសរើស <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ដើម្បីឱ្យស្ថិតក្រោមការគ្រប់គ្រងរបស់ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ឧបករណ៍"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"នាឡិកា"</string>
<string name="confirmation_title" msgid="4751119145078041732">"កំណត់ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ដើម្បីគ្រប់គ្រង <xliff:g id="PROFILE_NAME">%2$s</xliff:g> របស់អ្នក - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"ចាំបាច់ត្រូវមាន <xliff:g id="APP_NAME_0">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> របស់អ្នក។ <xliff:g id="APP_NAME2">%3$s</xliff:g> នឹងអាចចូលប្រើ <xliff:g id="PERMISSIONS">%4$s</xliff:g> នៅពេលភ្ជាប់ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>។"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"ចាំបាច់ត្រូវមាន <xliff:g id="APP_NAME">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="PROFILE_NAME">%2$s</xliff:g> របស់អ្នក។ <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"បាទ/ចាស"</string>
<string name="consent_no" msgid="1335543792857823917">"ទេ អរគុណ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
index 47cf76c..f4ae18f 100644
--- a/packages/CompanionDeviceManager/res/values-kn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ಕಂಪ್ಯಾನಿಯನ್ ಸಾಧನ ನಿರ್ವಾಹಕರು"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ಮೂಲಕ ನಿರ್ವಹಿಸಬೇಕಾದ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ಸಾಧನ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"ನಿಮ್ಮ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ಅನ್ನು ನಿರ್ವಹಿಸಲು, <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಅನ್ನು ನಿರ್ವಹಿಸಿ"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು, <xliff:g id="APP_NAME_0">%1$s</xliff:g> ಅಗತ್ಯವಿದೆ. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ಕನೆಕ್ಟ್ ಆದಾಗ, <xliff:g id="PERMISSIONS">%4$s</xliff:g> ಗೆ <xliff:g id="APP_NAME2">%3$s</xliff:g> ಪ್ರವೇಶವನ್ನು ಪಡೆಯುತ್ತದೆ."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ಹೌದು"</string>
<string name="consent_no" msgid="1335543792857823917">"ಬೇಡ, ಧನ್ಯವಾದಗಳು"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
index f2904138..1363e57 100644
--- a/packages/CompanionDeviceManager/res/values-ko/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"부속 기기 관리자"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>에서 관리할 <xliff:g id="PROFILE_NAME">%1$s</xliff:g>을(를) 선택"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"기기"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"시계"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>에서 <xliff:g id="PROFILE_NAME">%2$s</xliff:g>(<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)을(를) 관리하도록 설정"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>을(를) 관리하려면 <xliff:g id="APP_NAME_0">%1$s</xliff:g> 앱이 필요합니다. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>이(가) 연결되어 있는 동안 <xliff:g id="APP_NAME2">%3$s</xliff:g> 앱이 <xliff:g id="PERMISSIONS">%4$s</xliff:g>에 액세스할 수 있습니다."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> 프로필을 관리하려면 <xliff:g id="APP_NAME">%1$s</xliff:g> 앱이 필요합니다. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"예"</string>
<string name="consent_no" msgid="1335543792857823917">"취소"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
index 9cce298..c01e235 100644
--- a/packages/CompanionDeviceManager/res/values-ky/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<xliff:g id="PROFILE_NAME">%1$s</xliff:g> <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> тарабынан башкарылсын"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"түзмөк"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"саат"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> түзмөгүңүздү башкарсын"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> профилиңизди башкаруу үчүн <xliff:g id="APP_NAME_0">%1$s</xliff:g> керек. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> туташып турганда <xliff:g id="APP_NAME2">%3$s</xliff:g> колдонмосунун төмөнкүлөргө уруксаты болот: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> профилиңизди башкаруу үчүн <xliff:g id="APP_NAME">%1$s</xliff:g> керек. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ооба"</string>
<string name="consent_no" msgid="1335543792857823917">"Жок, рахмат"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
index 5fcbf7df..68218dd 100644
--- a/packages/CompanionDeviceManager/res/values-lo/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"ຕົວຈັດການອຸປະກອນປະກອບ"</string>
<string name="chooser_title" msgid="2262294130493605839">"ເລືອກ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ເພື່ອໃຫ້ຖືກຈັດການໂດຍ <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ອຸປະກອນ"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ໂມງ"</string>
<string name="confirmation_title" msgid="4751119145078041732">"ຕັ້ງ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ເພື່ອຈັດການ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ຂອງທ່ານ"</string>
- <string name="profile_summary" msgid="3167701603666642104">"ຕ້ອງໃຊ້ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ເພື່ອຈັດການ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ຂອງທ່ານ. <xliff:g id="APP_NAME2">%3$s</xliff:g> ຈະໄດ້ຮັບສິດເຂົ້າເຖິງ <xliff:g id="PERMISSIONS">%4$s</xliff:g> ໃນເວລາເຊື່ອມຕໍ່ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"ຕ້ອງໃຊ້ <xliff:g id="APP_NAME">%1$s</xliff:g> ເພື່ອຈັດການ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> ຂອງທ່ານ. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"ແມ່ນແລ້ວ"</string>
<string name="consent_no" msgid="1335543792857823917">"ບໍ່, ຂອບໃຈ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
index 56930d3..5fd8280 100644
--- a/packages/CompanionDeviceManager/res/values-lt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Jūsų <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, kurį valdys <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> (pasirinkite)"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"įrenginys"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"laikrodis"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Nustatyti, kad <xliff:g id="PROFILE_NAME">%2$s</xliff:g> <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> būtų valdomas programos <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Tam, kad būtų valdomas jūsų <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>, reikalinga programa „<xliff:g id="APP_NAME_0">%1$s</xliff:g>“. Kol prijungtas <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>, „<xliff:g id="APP_NAME2">%3$s</xliff:g>“ gaus prieigą prie šių elementų: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Norint valdyti jūsų <xliff:g id="PROFILE_NAME">%2$s</xliff:g>, reikalinga programa „<xliff:g id="APP_NAME">%1$s</xliff:g>“. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Taip"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, ačiū"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
index a9d2151..bf036ec 100644
--- a/packages/CompanionDeviceManager/res/values-lv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Palīgierīču pārzinis"</string>
<string name="chooser_title" msgid="2262294130493605839">"Profila (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>) izvēle, ko pārvaldīt lietotnē <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ierīce"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"pulkstenis"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Lietotnes <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> iestatīšana profila (<xliff:g id="PROFILE_NAME">%2$s</xliff:g> — <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>) pārvaldībai"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Lai pārvaldītu profilu (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>), nepieciešama lietotne <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Kamēr profils (<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>) būs pievienots, lietotnei <xliff:g id="APP_NAME2">%3$s</xliff:g> tiks piešķirta piekļuve šādām atļaujām: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Lai pārvaldītu profilu (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>), nepieciešama lietotne <xliff:g id="APP_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Jā"</string>
<string name="consent_no" msgid="1335543792857823917">"Nē, paldies"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
index 5cc18c5..427ca8f 100644
--- a/packages/CompanionDeviceManager/res/values-mk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Изберете <xliff:g id="PROFILE_NAME">%1$s</xliff:g> со којшто ќе управува <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"уред"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"часовник"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Поставете ја <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да управува со <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> е потребна за да управува со <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> ќе добие пристап до <xliff:g id="PERMISSIONS">%4$s</xliff:g> додека <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> е поврзан."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> е потребна за да управува со <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Да"</string>
<string name="consent_no" msgid="1335543792857823917">"Не, фала"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
index b6734e8..a48c45f 100644
--- a/packages/CompanionDeviceManager/res/values-ml/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"കമ്പാനിയൻ ഉപകരണ മാനേജർ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ഉപയോഗിച്ച് മാനേജ് ചെയ്യുന്നതിന് ഒരു <xliff:g id="PROFILE_NAME">%1$s</xliff:g> തിരഞ്ഞെടുക്കുക"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ഉപകരണം"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"വാച്ച്"</string>
<string name="confirmation_title" msgid="4751119145078041732">"നിങ്ങളുടെ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> മാനേജ് ചെയ്യുന്നതിന് <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> സജ്ജീകരിക്കുക - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> എന്ന ആപ്പിന് നിങ്ങളുടെ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> മാനേജ് ചെയ്യേണ്ടതുണ്ട്. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> കണക്റ്റ് ചെയ്തിരിക്കുമ്പോൾ <xliff:g id="APP_NAME2">%3$s</xliff:g> എന്ന ആപ്പിന് <xliff:g id="PERMISSIONS">%4$s</xliff:g> എന്നിവയിലേക്ക് ആക്സസ് ലഭിക്കും."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്ന ആപ്പിന് നിങ്ങളുടെ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> മാനേജ് ചെയ്യേണ്ടതുണ്ട്. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"വേണം"</string>
<string name="consent_no" msgid="1335543792857823917">"വേണ്ട"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
index cd4fdbf..7ac20e6 100644
--- a/packages/CompanionDeviceManager/res/values-mn/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>-н удирдах<xliff:g id="PROFILE_NAME">%1$s</xliff:g>-г сонгоно уу"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"төхөөрөмж"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"цаг"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g>-аа удирдахын тулд <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-г тохируулна уу - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Таны <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>-г удирдахын тулд <xliff:g id="APP_NAME_0">%1$s</xliff:g> шаардлагатай. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> холбогдсон үед <xliff:g id="APP_NAME2">%3$s</xliff:g> нь <xliff:g id="PERMISSIONS">%4$s</xliff:g>-д хандах эрхтэй болно."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Таны <xliff:g id="PROFILE_NAME">%2$s</xliff:g>-г удирдахын тулд <xliff:g id="APP_NAME">%1$s</xliff:g> шаардлагатай. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Тийм"</string>
<string name="consent_no" msgid="1335543792857823917">"Үгүй, баярлалаа"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
index 65bf262..68f9109 100644
--- a/packages/CompanionDeviceManager/res/values-mr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"सहयोगी डिव्हाइस व्यवस्थापक"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> द्वारे व्यवस्थापित करण्यासाठी <xliff:g id="PROFILE_NAME">%1$s</xliff:g> निवडा"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"डिव्हाइस"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"तुमची <xliff:g id="PROFILE_NAME">%2$s</xliff:g> व्यवस्थापित करण्यासाठी <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> सेट करा - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"तुमची <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> व्यवस्थापित करण्यासाठी <xliff:g id="APP_NAME_0">%1$s</xliff:g> आवश्यक आहे. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> कनेक्ट केलेली असताना <xliff:g id="APP_NAME2">%3$s</xliff:g> ला <xliff:g id="PERMISSIONS">%4$s</xliff:g> चा अॅक्सेस मिळेल."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"होय"</string>
<string name="consent_no" msgid="1335543792857823917">"नाही, नको"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
index d17041f..1188922 100644
--- a/packages/CompanionDeviceManager/res/values-ms/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Pengurus Peranti Rakan"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pilih <xliff:g id="PROFILE_NAME">%1$s</xliff:g> untuk diurus oleh <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"peranti"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Tetapkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> untuk mengurus <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> anda"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> diperlukan untuk mengurus <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> anda. <xliff:g id="APP_NAME2">%3$s</xliff:g> akan mendapat akses kepada <xliff:g id="PERMISSIONS">%4$s</xliff:g> semasa <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> disambungkan."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Ya"</string>
<string name="consent_no" msgid="1335543792857823917">"Tidak perlu"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
index 23f165a..9c2783c 100644
--- a/packages/CompanionDeviceManager/res/values-my/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"တွဲဖက်ကိရိယာ မန်နေဂျာ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> က စီမံခန့်ခွဲရန် <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ကို ရွေးချယ်ပါ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"စက်"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"နာရီ"</string>
<string name="confirmation_title" msgid="4751119145078041732">"သင်၏ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ကို စီမံခန့်ခွဲရန် <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ကို သတ်မှတ်ပါ"</string>
- <string name="profile_summary" msgid="3167701603666642104">"သင်၏ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ကို စီမံခန့်ခွဲရန် <xliff:g id="APP_NAME_0">%1$s</xliff:g> ကို လိုအပ်ပါသည်။ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ကို ချိတ်ဆက်ထားစဉ် <xliff:g id="APP_NAME2">%3$s</xliff:g> သည် <xliff:g id="PERMISSIONS">%4$s</xliff:g> ကို ဝင်သုံးခွင့်ရပါမည်။"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"သင်၏ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> ကို စီမံခန့်ခွဲရန် <xliff:g id="APP_NAME">%1$s</xliff:g> ကို လိုအပ်ပါသည်။ <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Yes"</string>
<string name="consent_no" msgid="1335543792857823917">"မလိုပါ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
index 090f2a2..26fbb03 100644
--- a/packages/CompanionDeviceManager/res/values-nb/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Velg <xliff:g id="PROFILE_NAME">%1$s</xliff:g> som skal administreres av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"klokke"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Angi <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> for å administrere <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> kreves for å administrere <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> får tilgang til <xliff:g id="PERMISSIONS">%4$s</xliff:g> når <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> er tilkoblet."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> kreves for å administrere <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nei takk"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
index e885674..f289b37 100644
--- a/packages/CompanionDeviceManager/res/values-ne/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"सहयोगी यन्त्रको प्रबन्धक"</string>
<string name="chooser_title" msgid="2262294130493605839">"आफूले <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> प्रयोग गरी व्यवस्थापन गर्न चाहेको <xliff:g id="PROFILE_NAME">%1$s</xliff:g> चयन गर्नुहोस्"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"यन्त्र"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"घडी"</string>
<string name="confirmation_title" msgid="4751119145078041732">"आफ्नो <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> व्यवस्थापन गर्न <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> तोक्नुहोस्"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> व्यवस्थापन गर्न <xliff:g id="APP_NAME_0">%1$s</xliff:g> इन्स्टल गर्नु पर्ने हुन्छ। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> कनेक्ट भएका बेला <xliff:g id="APP_NAME2">%3$s</xliff:g> ले <xliff:g id="PERMISSIONS">%4$s</xliff:g> प्रयोग गर्ने अनुमति प्राप्त गर्ने छ।"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> व्यवस्थापन गर्न <xliff:g id="APP_NAME">%1$s</xliff:g> इन्स्टल गर्नु पर्ने हुन्छ। <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"अँ"</string>
<string name="consent_no" msgid="1335543792857823917">"सहमत छुइनँ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
index 5a7fb3a..0c9cdffd 100644
--- a/packages/CompanionDeviceManager/res/values-nl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Een <xliff:g id="PROFILE_NAME">%1$s</xliff:g> kiezen om te beheren met <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"apparaat"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"horloge"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> instellen om je <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> te beheren"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Je hebt <xliff:g id="APP_NAME_0">%1$s</xliff:g> nodig om je <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> te beheren. <xliff:g id="APP_NAME2">%3$s</xliff:g> krijgt toegang tot <xliff:g id="PERMISSIONS">%4$s</xliff:g> terwijl je <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> is verbonden."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Je hebt <xliff:g id="APP_NAME">%1$s</xliff:g> nodig om je <xliff:g id="PROFILE_NAME">%2$s</xliff:g> te beheren. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nee, bedankt"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
index 03fae5c..d1aa50b 100644
--- a/packages/CompanionDeviceManager/res/values-or/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ସହଯୋଗୀ ଡିଭାଇସ୍ ପରିଚାଳକ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ଦ୍ୱାରା ପରିଚାଳିତ ହେବା ପାଇଁ ଏକ <xliff:g id="PROFILE_NAME">%1$s</xliff:g>କୁ ବାଛନ୍ତୁ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ଡିଭାଇସ୍"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"ଆପଣଙ୍କ <xliff:g id="PROFILE_NAME">%2$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>କୁ ସେଟ୍ କରନ୍ତୁ - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"ଆପଣଙ୍କ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>କୁ ପରିଚାଳନା କରିବା ପାଇଁ <xliff:g id="APP_NAME_0">%1$s</xliff:g>ର ଆବଶ୍ୟକତା ଅଛି। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ସଂଯୁକ୍ତ ହୋଇଥିବା ସମୟରେ <xliff:g id="APP_NAME2">%3$s</xliff:g> <xliff:g id="PERMISSIONS">%4$s</xliff:g>କୁ ଆକ୍ସେସ୍ ପାଇବ।"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ହଁ"</string>
<string name="consent_no" msgid="1335543792857823917">"ନା, ଧନ୍ୟବାଦ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
index 33135b2..ff211f2 100644
--- a/packages/CompanionDeviceManager/res/values-pa/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ਸੰਬੰਧੀ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਕ"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤੇ ਜਾਣ ਲਈ <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ਚੁਣੋ"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"ਡੀਵਾਈਸ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ ਤੁਹਾਡਾ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਲਈ ਸੈੱਟ ਕਰੋ"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ਨੂੰ ਤੁਹਾਡਾ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ ਦੀ ਲੋੜ ਹੈ। <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ਕਨੈਕਟ ਕੀਤੇ ਹੋਣ \'ਤੇ <xliff:g id="APP_NAME2">%3$s</xliff:g> ਨੂੰ <xliff:g id="PERMISSIONS">%4$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਹੋ ਜਾਵੇਗੀ।"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ਹਾਂ"</string>
<string name="consent_no" msgid="1335543792857823917">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
index a828370..b07af57 100644
--- a/packages/CompanionDeviceManager/res/values-pl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Menedżer urządzeń towarzyszących"</string>
<string name="chooser_title" msgid="2262294130493605839">"Wybierz profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, którym ma zarządzać aplikacja <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"urządzenie"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"zegarek"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Ustaw aplikację <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> do zarządzania profilem <xliff:g id="PROFILE_NAME">%2$s</xliff:g> na urządzeniu <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Aplikacja <xliff:g id="APP_NAME_0">%1$s</xliff:g> jest wymagana do zarządzania profilem <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Kiedy profil <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> będzie połączony, <xliff:g id="APP_NAME2">%3$s</xliff:g> będzie mieć te uprawnienia: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> jest wymagana do zarządzania profilem <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Tak"</string>
<string name="consent_no" msgid="1335543792857823917">"Nie, dziękuję"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
index 4258e70..16906f6 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Defina o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> como gerenciador do seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> é necessário para gerenciar seu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> terá acesso a <xliff:g id="PERMISSIONS">%4$s</xliff:g> enquanto o <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> estiver conectado."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> é necessário para gerenciar seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Sim"</string>
<string name="consent_no" msgid="1335543792857823917">"Agora não"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
index 45b03d6..745d163 100644
--- a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos associados"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerido pela app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Defina a app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> para gerir o seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"A app <xliff:g id="APP_NAME_0">%1$s</xliff:g> é necessária para gerir o seu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. A app <xliff:g id="APP_NAME2">%3$s</xliff:g> terá acesso a <xliff:g id="PERMISSIONS">%4$s</xliff:g> enquanto o <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> estiver associado."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> é necessária para gerir o seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Sim"</string>
<string name="consent_no" msgid="1335543792857823917">"Não, obrigado"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
index 4258e70..16906f6 100644
--- a/packages/CompanionDeviceManager/res/values-pt/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
<string name="chooser_title" msgid="2262294130493605839">"Escolha um <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para ser gerenciado pelo app <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispositivo"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"relógio"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Defina o app <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> como gerenciador do seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> (<strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"O app <xliff:g id="APP_NAME_0">%1$s</xliff:g> é necessário para gerenciar seu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> terá acesso a <xliff:g id="PERMISSIONS">%4$s</xliff:g> enquanto o <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> estiver conectado."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> é necessário para gerenciar seu <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Sim"</string>
<string name="consent_no" msgid="1335543792857823917">"Agora não"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
index 060e996..187cfbdf 100644
--- a/packages/CompanionDeviceManager/res/values-ro/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Manager de dispozitiv Companion"</string>
<string name="chooser_title" msgid="2262294130493605839">"Alegeți un profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> pe care să îl gestioneze <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"dispozitiv"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ceas"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Setați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> pentru a vă gestiona profilul <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> este necesară pentru a vă gestiona profilul <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> va primi acces la <xliff:g id="PERMISSIONS">%4$s</xliff:g> în timp ce profilul <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> este conectat."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> este necesară pentru a vă gestiona profilul <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Nu, mulțumesc"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
index 7982507..8dd9a39 100644
--- a/packages/CompanionDeviceManager/res/values-ru/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Управление подключенными устройствами"</string>
<string name="chooser_title" msgid="2262294130493605839">"Выберите устройство (<xliff:g id="PROFILE_NAME">%1$s</xliff:g>), которым будет управлять приложение <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"устройство"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"часы"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Разрешите приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> управлять устройством <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Приложение \"<xliff:g id="APP_NAME_0">%1$s</xliff:g>\" необходимо для управления устройством (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>). При подключении к устройству (<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>) приложение \"<xliff:g id="APP_NAME2">%3$s</xliff:g>\" получит доступ к следующему: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" необходимо для управления устройством (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>). <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Да"</string>
<string name="consent_no" msgid="1335543792857823917">"Нет"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
index 8bbc1a6..9e7c02e 100644
--- a/packages/CompanionDeviceManager/res/values-si/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"සහායක උපාංග කළමනාකරු"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> මගින් කළමනාකරණය කරනු ලැබීමට <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ක් තෝරන්න"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"උපාංගය"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ඔරලෝසුව"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ඔබගේ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> කළමනාකරණය කිරීමට සකසන්න - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ඔබගේ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> කළමනාකරණය කිරීමට අවශ්යයි. <xliff:g id="APP_NAME2">%3$s</xliff:g> හට <xliff:g id="PERMISSIONS">%4$s</xliff:g> වෙත ප්රවේශය <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> සම්බන්ධිත අතරතුර ලැබෙනු ඇත."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"ඔබගේ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> කළමනාකරණය කිරීමට <xliff:g id="APP_NAME">%1$s</xliff:g> අවශ්යයි. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"ඔව්"</string>
<string name="consent_no" msgid="1335543792857823917">"එපා, ස්තුතියි"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
index 1037a96..55a47c2 100644
--- a/packages/CompanionDeviceManager/res/values-sk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Správca sprievodných zariadení"</string>
<string name="chooser_title" msgid="2262294130493605839">"Vyberte profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ktorý bude spravovať aplikácia <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"zariadenie"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"hodinky"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Nastavte aplikáciu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>, aby spravovala profil <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Na správu profilu <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> je potrebná aplikácia <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Kým bude profil <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> pripojený, <xliff:g id="APP_NAME2">%3$s</xliff:g> získa prístup k povoleniam <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Na správu profilu <xliff:g id="PROFILE_NAME">%2$s</xliff:g> je potrebná aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Áno"</string>
<string name="consent_no" msgid="1335543792857823917">"Nie, vďaka"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
index f2d4c6f..159afd5 100644
--- a/packages/CompanionDeviceManager/res/values-sl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Upravitelj spremljevalnih naprav"</string>
<string name="chooser_title" msgid="2262294130493605839">"Izbira naprave <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, ki jo bo upravljala aplikacija <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"naprava"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"ura"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Nastavitev aplikacije <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>, ki bo upravljala napravo <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Za upravljanje naprave <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> potrebujete aplikacijo <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Ko je naprava <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> povezana, bo aplikaciji <xliff:g id="APP_NAME2">%3$s</xliff:g> omogočen dostop do teh dovoljenj: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Za upravljanje naprave <xliff:g id="PROFILE_NAME">%2$s</xliff:g> potrebujete aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Da"</string>
<string name="consent_no" msgid="1335543792857823917">"Ne, hvala"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
index c9336b3..4c308e8 100644
--- a/packages/CompanionDeviceManager/res/values-sq/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"Menaxheri i pajisjes shoqëruese"</string>
<string name="chooser_title" msgid="2262294130493605839">"Zgjidh një profil <xliff:g id="PROFILE_NAME">%1$s</xliff:g> që do të menaxhohet nga <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"pajisja"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"Cakto <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> që të menaxhojë profilin tënd <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Nevojitet <xliff:g id="APP_NAME_0">%1$s</xliff:g> për të menaxhuar profilin tënd <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> do të marrë qasje në <xliff:g id="PERMISSIONS">%4$s</xliff:g> ndërkohë që është lidhur profili <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"Po"</string>
<string name="consent_no" msgid="1335543792857823917">"Jo, faleminderit"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
index 5298194..fdbbe8e 100644
--- a/packages/CompanionDeviceManager/res/values-sr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Менаџер придруженог уређаја"</string>
<string name="chooser_title" msgid="2262294130493605839">"Одаберите профил <xliff:g id="PROFILE_NAME">%1$s</xliff:g> којим ће управљати апликација <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"уређај"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"сат"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Подесите апликацију <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> да управља профилом <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Апликација <xliff:g id="APP_NAME_0">%1$s</xliff:g> је неопходна за управљање профилом <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> ће добити приступ дозволама за <xliff:g id="PERMISSIONS">%4$s</xliff:g> док је <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> повезан."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је неопходна за управљање профилом <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Да"</string>
<string name="consent_no" msgid="1335543792857823917">"Не, хвала"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
index caacba0..bfd2516 100644
--- a/packages/CompanionDeviceManager/res/values-sv/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Välj en <xliff:g id="PROFILE_NAME">%1$s</xliff:g> för hantering av <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"enhet"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"klocka"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Konfigurera <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> för att hantera din <xliff:g id="PROFILE_NAME">%2$s</xliff:g> – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> krävs för att hantera din <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. <xliff:g id="APP_NAME2">%3$s</xliff:g> får åtkomst till <xliff:g id="PERMISSIONS">%4$s</xliff:g> medan <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> är ansluten."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> krävs för att hantera din <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ja"</string>
<string name="consent_no" msgid="1335543792857823917">"Nej tack"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
index ae8ade7..437ae7f 100644
--- a/packages/CompanionDeviceManager/res/values-sw/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Kidhibiti cha Vifaa Visaidizi"</string>
<string name="chooser_title" msgid="2262294130493605839">"Chagua <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ili idhibitiwe na <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"kifaa"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"saa"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Weka <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ili udhibiti <xliff:g id="PROFILE_NAME">%2$s</xliff:g> yako - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> linahitajika ili kudhibiti <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> wako. <xliff:g id="APP_NAME2">%3$s</xliff:g> itapata uwezo wa kufikia <xliff:g id="PERMISSIONS">%4$s</xliff:g> wakati <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> imeunganishwa."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> linahitajika ili kudhibiti <xliff:g id="PROFILE_NAME">%2$s</xliff:g> yako. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ndiyo"</string>
<string name="consent_no" msgid="1335543792857823917">"Hapana"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
index 373ed45..9b4a720 100644
--- a/packages/CompanionDeviceManager/res/values-ta/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"கம்பேனியன் சாதன நிர்வாகி"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ஆப்ஸ் நிர்வகிக்கக்கூடிய <xliff:g id="PROFILE_NAME">%1$s</xliff:g> ஐத் தேர்ந்தெடுங்கள்"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"சாதனம்"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"வாட்ச்"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> ஐ நிர்வகிக்க <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை அமையுங்கள்"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> ஐ நிர்வகிக்க <xliff:g id="APP_NAME_0">%1$s</xliff:g> ஆப்ஸ் வேண்டும். <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> இணைக்கப்பட்டதும் <xliff:g id="PERMISSIONS">%4$s</xliff:g> ஆகியவற்றுக்கான அணுகலை <xliff:g id="APP_NAME2">%3$s</xliff:g> ஆப்ஸ் பெறும்."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> ஐ நிர்வகிக்க <xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் வேண்டும். <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"ஆம்"</string>
<string name="consent_no" msgid="1335543792857823917">"வேண்டாம்"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
index f73e713..6e785de 100644
--- a/packages/CompanionDeviceManager/res/values-te/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"సహచర పరికర మేనేజర్"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> ద్వారా మేనేజ్ చేయబడటానికి ఒక <xliff:g id="PROFILE_NAME">%1$s</xliff:g>ను ఎంచుకోండి"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"పరికరం"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"వాచ్"</string>
<string name="confirmation_title" msgid="4751119145078041732">"మీ <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>ను మేనేజ్ చేయడానికి <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ను సెటప్ చేయండి"</string>
- <string name="profile_summary" msgid="3167701603666642104">"మీ <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>ను మేనేజ్ చేయడానికి <xliff:g id="APP_NAME_0">%1$s</xliff:g> అవసరం ఉంది. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> కనెక్ట్ అయినప్పుడు <xliff:g id="APP_NAME2">%3$s</xliff:g>, <xliff:g id="PERMISSIONS">%4$s</xliff:g>కు యాక్సెస్ను పొందుతుంది."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"మీ <xliff:g id="PROFILE_NAME">%2$s</xliff:g>ను మేనేజ్ చేయడానికి <xliff:g id="APP_NAME">%1$s</xliff:g> అవసరం ఉంది. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"అవును"</string>
<string name="consent_no" msgid="1335543792857823917">"వద్దు, ధన్యవాదాలు"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
index 8c1848a..b727d42 100644
--- a/packages/CompanionDeviceManager/res/values-th/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"เลือก<xliff:g id="PROFILE_NAME">%1$s</xliff:g>ที่จะให้มีการจัดการโดย <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"อุปกรณ์"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"นาฬิกา"</string>
<string name="confirmation_title" msgid="4751119145078041732">"ตั้งค่า <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ให้จัดการ<xliff:g id="PROFILE_NAME">%2$s</xliff:g>ของคุณ - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"ต้องใช้ <xliff:g id="APP_NAME_0">%1$s</xliff:g> ในการจัดการ<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> <xliff:g id="APP_NAME2">%3$s</xliff:g> จะได้รับสิทธิ์เข้าถึง<xliff:g id="PERMISSIONS">%4$s</xliff:g>ในขณะที่มีการเชื่อมต่อ<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"ต้องใช้ <xliff:g id="APP_NAME">%1$s</xliff:g> ในการจัดการ<xliff:g id="PROFILE_NAME">%2$s</xliff:g> <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"ใช่"</string>
<string name="consent_no" msgid="1335543792857823917">"ไม่เป็นไร"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
index 8fcc3d2..a93282a 100644
--- a/packages/CompanionDeviceManager/res/values-tl/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Kasamang Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Pumili ng <xliff:g id="PROFILE_NAME">%1$s</xliff:g> para pamahalaan ng <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"device"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"relo"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Itakda ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> para pamahalaan ang iyong <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Kailangan ang <xliff:g id="APP_NAME_0">%1$s</xliff:g> para pamahalaan ang iyong <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>. Magkakaroon ng access ang <xliff:g id="APP_NAME2">%3$s</xliff:g> sa <xliff:g id="PERMISSIONS">%4$s</xliff:g> habang nakakonekta ang <xliff:g id="PROFILE_NAME2">%5$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Kailangan ang <xliff:g id="APP_NAME">%1$s</xliff:g> para pamahalaan ang iyong <xliff:g id="PROFILE_NAME">%2$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Oo"</string>
<string name="consent_no" msgid="1335543792857823917">"Huwag na lang"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
index 255eca5..3abe064 100644
--- a/packages/CompanionDeviceManager/res/values-tr/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> tarafından yönetilecek bir <xliff:g id="PROFILE_NAME">%1$s</xliff:g> seçin"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"cihaz"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"saat"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasını, <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> cihazınızı yönetecek şekilde ayarlayın"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g>, <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> yönetimi için gereklidir. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> bağlıyken <xliff:g id="APP_NAME2">%3$s</xliff:g>, şunlara erişebilecek: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="PROFILE_NAME">%2$s</xliff:g> yönetimi için gereklidir. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Evet"</string>
<string name="consent_no" msgid="1335543792857823917">"Hayır, teşekkürler"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
index b5827f2..161d95e 100644
--- a/packages/CompanionDeviceManager/res/values-uk/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Диспетчер супутніх пристроїв"</string>
<string name="chooser_title" msgid="2262294130493605839">"Виберіть <xliff:g id="PROFILE_NAME">%1$s</xliff:g>, яким керуватиме додаток <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"пристрій"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"годинник"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Налаштуйте додаток <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>, щоб керувати своїм пристроєм <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>)"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Щоб керувати своїм пристроєм (<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>), вам потрібен додаток <xliff:g id="APP_NAME_0">%1$s</xliff:g>. Коли <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> буде підключено, додаток <xliff:g id="APP_NAME2">%3$s</xliff:g> отримає такі дозволи на доступ: <xliff:g id="PERMISSIONS">%4$s</xliff:g>."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Щоб керувати своїм пристроєм (<xliff:g id="PROFILE_NAME">%2$s</xliff:g>), вам потрібен додаток <xliff:g id="APP_NAME">%1$s</xliff:g>. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Так"</string>
<string name="consent_no" msgid="1335543792857823917">"Ні, дякую"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
index 2bbffdc..967b7f9 100644
--- a/packages/CompanionDeviceManager/res/values-ur/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -19,8 +19,11 @@
<string name="app_label" msgid="4470785958457506021">"ساتھی آلہ مینیجر"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> کے ذریعے نظم کئے جانے کیلئے <xliff:g id="PROFILE_NAME">%1$s</xliff:g> کو منتخب کریں"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"آلہ"</string>
+ <!-- no translation found for profile_name_watch (576290739483672360) -->
+ <skip />
<string name="confirmation_title" msgid="4751119145078041732">"اپنے <xliff:g id="PROFILE_NAME">%2$s</xliff:g> کا نظم کرنے کے لیے <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو سیٹ کریں - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"آپ کے <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> کا نظم کرنے کے لیے <xliff:g id="APP_NAME_0">%1$s</xliff:g> کی ضرورت ہے۔ <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> کے منسلک ہونے پر <xliff:g id="APP_NAME2">%3$s</xliff:g> <xliff:g id="PERMISSIONS">%4$s</xliff:g> تک رسائی حاصل کرے گا۔"</string>
+ <!-- no translation found for profile_summary (2009764182871566255) -->
+ <skip />
<string name="consent_yes" msgid="4055438216605487056">"ہاں"</string>
<string name="consent_no" msgid="1335543792857823917">"نہیں شکریہ"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
index 96c49f2..4cce2e8 100644
--- a/packages/CompanionDeviceManager/res/values-uz/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> boshqaradigan <xliff:g id="PROFILE_NAME">%1$s</xliff:g> qurilmasini tanlang"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"qurilma"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"tomosha qilish"</string>
<string name="confirmation_title" msgid="4751119145078041732">"<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong> qurilmalarini boshqarish uchun <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasini sozlang"</string>
- <string name="profile_summary" msgid="3167701603666642104">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ilovasi <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> qurilmasini boshqarish uchun kerak. <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> qurilmasiga <xliff:g id="APP_NAME2">%3$s</xliff:g> ilovasi ulansa, u quyidagi ruxsatlarni oladi: <xliff:g id="PERMISSIONS">%4$s</xliff:g>"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi <xliff:g id="PROFILE_NAME">%2$s</xliff:g> qurilmasini boshqarish uchun kerak. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Ha"</string>
<string name="consent_no" msgid="1335543792857823917">"Kerak emas"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
index d67db41..06a1ab6 100644
--- a/packages/CompanionDeviceManager/res/values-vi/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
<string name="chooser_title" msgid="2262294130493605839">"Chọn một <xliff:g id="PROFILE_NAME">%1$s</xliff:g> sẽ do <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> quản lý"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"thiết bị"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"đồng hồ"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Đặt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> để quản lý <xliff:g id="PROFILE_NAME">%2$s</xliff:g> của bạn – <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"Cần có <xliff:g id="APP_NAME_0">%1$s</xliff:g> để quản lý <xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> của bạn. <xliff:g id="APP_NAME2">%3$s</xliff:g> sẽ có quyền truy cập vào <xliff:g id="PERMISSIONS">%4$s</xliff:g> trong khi <xliff:g id="PROFILE_NAME2">%5$s</xliff:g> được kết nối."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"Cần có <xliff:g id="APP_NAME">%1$s</xliff:g> để quản lý <xliff:g id="PROFILE_NAME">%2$s</xliff:g> của bạn. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Có"</string>
<string name="consent_no" msgid="1335543792857823917">"Không, cảm ơn"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
index a1abd98..12bfcf3 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"配套设备管理器"</string>
<string name="chooser_title" msgid="2262294130493605839">"选择要由<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"设备"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"手表"</string>
<string name="confirmation_title" msgid="4751119145078041732">"设为由<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>管理您的<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"若要管理<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>,您需要使用<xliff:g id="APP_NAME_0">%1$s</xliff:g>。在已连接<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>的情况下,<xliff:g id="APP_NAME2">%3$s</xliff:g>将能够访问<xliff:g id="PERMISSIONS">%4$s</xliff:g>。"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"若要管理<xliff:g id="PROFILE_NAME">%2$s</xliff:g>,您需要使用<xliff:g id="APP_NAME">%1$s</xliff:g>。<xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"好"</string>
<string name="consent_no" msgid="1335543792857823917">"不用了"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
index 57d2173..0c583b2 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"隨附裝置管理員"</string>
<string name="chooser_title" msgid="2262294130493605839">"選擇由 <strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong> 管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
<string name="confirmation_title" msgid="4751119145078041732">"設定 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 來管理您的 <xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"必須使用 <xliff:g id="APP_NAME_0">%1$s</xliff:g> 來管理您的<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>。連結<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>後,<xliff:g id="APP_NAME2">%3$s</xliff:g> 將可以存取<xliff:g id="PERMISSIONS">%4$s</xliff:g>。"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"必須使用 <xliff:g id="APP_NAME">%1$s</xliff:g> 來管理您的<xliff:g id="PROFILE_NAME">%2$s</xliff:g>。<xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"是"</string>
<string name="consent_no" msgid="1335543792857823917">"不用了,謝謝"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
index c9a2fd8..519f0e8 100644
--- a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"隨附裝置管理員"</string>
<string name="chooser_title" msgid="2262294130493605839">"選擇要讓「<xliff:g id="APP_NAME">%2$s</xliff:g>」<strong></strong>管理的<xliff:g id="PROFILE_NAME">%1$s</xliff:g>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"裝置"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"手錶"</string>
<string name="confirmation_title" msgid="4751119145078041732">"授權讓「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>管理你的<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"如要管理你的<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g>,必須使用「<xliff:g id="APP_NAME_0">%1$s</xliff:g>」。與<xliff:g id="PROFILE_NAME2">%5$s</xliff:g>連線時,「<xliff:g id="APP_NAME2">%3$s</xliff:g>」將有權存取你的<xliff:g id="PERMISSIONS">%4$s</xliff:g>。"</string>
+ <string name="profile_summary" msgid="2009764182871566255">"如要管理你的<xliff:g id="PROFILE_NAME">%2$s</xliff:g>,必須使用「<xliff:g id="APP_NAME">%1$s</xliff:g>」。<xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"是"</string>
<string name="consent_no" msgid="1335543792857823917">"不用了,謝謝"</string>
</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
index c811037..7721b54 100644
--- a/packages/CompanionDeviceManager/res/values-zu/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -19,8 +19,9 @@
<string name="app_label" msgid="4470785958457506021">"Isiphathi sedivayisi esihambisanayo"</string>
<string name="chooser_title" msgid="2262294130493605839">"Khetha i-<xliff:g id="PROFILE_NAME">%1$s</xliff:g> ezophathwa yi-<strong><xliff:g id="APP_NAME">%2$s</xliff:g></strong>"</string>
<string name="profile_name_generic" msgid="6851028682723034988">"idivayisi"</string>
+ <string name="profile_name_watch" msgid="576290739483672360">"buka"</string>
<string name="confirmation_title" msgid="4751119145078041732">"Setha i-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ukuba iphathe i-<xliff:g id="PROFILE_NAME">%2$s</xliff:g> - <strong><xliff:g id="DEVICE_NAME">%3$s</xliff:g></strong>"</string>
- <string name="profile_summary" msgid="3167701603666642104">"I-<xliff:g id="APP_NAME_0">%1$s</xliff:g> iyadingeka ukuphatha i-<xliff:g id="PROFILE_NAME_1">%2$s</xliff:g> yakho. I-<xliff:g id="APP_NAME2">%3$s</xliff:g> izothola ukufinyelela ku-<xliff:g id="PERMISSIONS">%4$s</xliff:g> kuyilapho i-<xliff:g id="PROFILE_NAME2">%5$s</xliff:g> ixhunyiwe."</string>
+ <string name="profile_summary" msgid="2009764182871566255">"I-<xliff:g id="APP_NAME">%1$s</xliff:g> iyadingeka ukuphatha i-<xliff:g id="PROFILE_NAME">%2$s</xliff:g> yakho. <xliff:g id="PRIVILEGES_DISCPLAIMER">%3$s</xliff:g>"</string>
<string name="consent_yes" msgid="4055438216605487056">"Yebo"</string>
<string name="consent_no" msgid="1335543792857823917">"Cha ngiyabonga"</string>
</resources>
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java
index 06c5294..35bc490 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java
@@ -19,11 +19,9 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.image.DynamicSystemClient;
import android.os.image.DynamicSystemManager;
-import android.util.FeatureFlagUtils;
/**
@@ -48,7 +46,7 @@
boolean isInUse = (dynSystem != null) && dynSystem.isInUse();
- if (!isInUse && !featureFlagEnabled()) {
+ if (!isInUse) {
return;
}
@@ -58,9 +56,4 @@
startServiceIntent.setAction(DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE);
context.startServiceAsUser(startServiceIntent, UserHandle.SYSTEM);
}
-
- private boolean featureFlagEnabled() {
- return SystemProperties.getBoolean(
- FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.DYNAMIC_SYSTEM, false);
- }
}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
index 82ea744..64e42cc 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
@@ -22,10 +22,8 @@
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.image.DynamicSystemClient;
-import android.util.FeatureFlagUtils;
import android.util.Log;
/**
@@ -46,12 +44,6 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (!featureFlagEnabled()) {
- Log.w(TAG, FeatureFlagUtils.DYNAMIC_SYSTEM + " not enabled; activity aborted.");
- finish();
- return;
- }
-
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (km != null) {
@@ -101,11 +93,6 @@
startServiceAsUser(intent, UserHandle.SYSTEM);
}
- private boolean featureFlagEnabled() {
- return SystemProperties.getBoolean(
- FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.DYNAMIC_SYSTEM, false);
- }
-
static boolean isVerified(String url) {
if (url == null) return true;
return sVerifiedUrl != null && sVerifiedUrl.equals(url);
diff --git a/packages/InputDevices/res/values-eu/strings.xml b/packages/InputDevices/res/values-eu/strings.xml
index 77d252d..eb95466 100644
--- a/packages/InputDevices/res/values-eu/strings.xml
+++ b/packages/InputDevices/res/values-eu/strings.xml
@@ -48,6 +48,6 @@
<string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerbaijandarra"</string>
<string name="keyboard_layout_polish" msgid="1121588624094925325">"Poloniarra"</string>
<string name="keyboard_layout_belarusian" msgid="7619281752698687588">"Bielorrusiera"</string>
- <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoliera"</string>
+ <string name="keyboard_layout_mongolian" msgid="7678483495823936626">"Mongoliarra"</string>
<string name="keyboard_layout_georgian" msgid="4596185456863747454">"Georgiera"</string>
</resources>
diff --git a/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveIcon.java b/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveIcon.java
index fc93650..723caf2 100644
--- a/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveIcon.java
+++ b/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveIcon.java
@@ -45,12 +45,15 @@
private AdaptiveConstantState mAdaptiveConstantState;
public AdaptiveIcon(Context context, Drawable foreground) {
+ this(context, foreground, R.dimen.dashboard_tile_foreground_image_inset);
+ }
+
+ public AdaptiveIcon(Context context, Drawable foreground, int insetResId) {
super(new Drawable[]{
new AdaptiveIconShapeDrawable(context.getResources()),
foreground
});
- final int insetPx = context.getResources()
- .getDimensionPixelSize(R.dimen.dashboard_tile_foreground_image_inset);
+ final int insetPx = context.getResources().getDimensionPixelSize(insetResId);
setLayerInset(1 /* index */, insetPx, insetPx, insetPx, insetPx);
mAdaptiveConstantState = new AdaptiveConstantState(context, foreground);
}
diff --git a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppPreference.java
similarity index 71%
rename from packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java
rename to packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppPreference.java
index e88ac56..cfe7013 100644
--- a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/apppreference/AppPreference.java
+++ b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppPreference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.widget.apppreference;
+package com.android.settingslib.widget;
import android.content.Context;
import android.util.AttributeSet;
@@ -24,13 +24,24 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
-import com.android.settingslib.widget.R;
-
+/**
+ * The Preference for the pages need to show apps icon.
+ */
public class AppPreference extends Preference {
private int mProgress;
private boolean mProgressVisible;
+ public AppPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setLayoutResource(R.layout.preference_app);
+ }
+
+ public AppPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setLayoutResource(R.layout.preference_app);
+ }
+
public AppPreference(Context context) {
super(context);
setLayoutResource(R.layout.preference_app);
@@ -41,6 +52,12 @@
setLayoutResource(R.layout.preference_app);
}
+ /**
+ * Sets the current progress.
+ * @param amount the current progress
+ *
+ * @see ProgressBar#setProgress(int)
+ */
public void setProgress(int amount) {
mProgress = amount;
mProgressVisible = true;
@@ -59,4 +76,4 @@
progress.setVisibility(View.GONE);
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppSwitchPreference.java b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppSwitchPreference.java
new file mode 100644
index 0000000..781bfcd
--- /dev/null
+++ b/packages/SettingsLib/AppPreference/src/com/android/settingslib/widget/AppSwitchPreference.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
+/**
+ * The SwitchPreference for the pages need to show apps icon.
+ */
+public class AppSwitchPreference extends SwitchPreference {
+
+ public AppSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setLayoutResource(R.layout.preference_app);
+ }
+
+ public AppSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ setLayoutResource(R.layout.preference_app);
+ }
+
+ public AppSwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLayoutResource(R.layout.preference_app);
+ }
+
+ public AppSwitchPreference(Context context) {
+ super(context);
+ setLayoutResource(R.layout.preference_app);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ final View switchView = holder.findViewById(android.R.id.switch_widget);
+ if (switchView != null) {
+ final View rootView = switchView.getRootView();
+ rootView.setFilterTouchesWhenObscured(true);
+ }
+ }
+}
diff --git a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on_background.xml b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on_background.xml
index 02e3a84..68ce19b 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on_background.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/drawable/track_on_background.xml
@@ -20,7 +20,8 @@
android:width="48dp"
android:height="24dp"
android:viewportWidth="48"
- android:viewportHeight="24">
+ android:viewportHeight="24"
+ android:tint="@*android:color/switch_track_material">
<group>
<clip-path
@@ -28,7 +29,7 @@
<path
android:pathData="M0 0V24H48V0"
- android:fillColor="@color/track_on" />
+ android:fillColor="@*android:color/white_disabled_material" />
</group>
</vector>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
index b1553e9..7e3ce9d 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
@@ -35,6 +35,7 @@
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
+ android:paddingRight="54dp"
android:layout_gravity="center_vertical"
android:maxLines="2"
android:ellipsize="end"
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml b/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
index ecbb84a..9dc0af3 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values-night/colors.xml
@@ -19,7 +19,6 @@
<color name="title_text_color">@*android:color/primary_text_dark</color>
<color name="thumb_off">#BFFFFFFF</color>
- <color name="track_on">@*android:color/material_grey_600</color>
<color name="track_off">@*android:color/material_grey_600</color>
</resources>
diff --git a/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml b/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
index ac8ab14..8194bdd 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/values/colors.xml
@@ -19,7 +19,6 @@
<color name="title_text_color">@*android:color/primary_text_light</color>
<color name="thumb_off">#BFFFFFFF</color>
- <color name="track_on">@*android:color/accent_device_default_dark</color>
<color name="track_off">@*android:color/material_grey_600</color>
</resources>
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 93f00e7..ca409f37 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktief (media)"</item>
<item msgid="5001852592115448348">", aktief (foon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Af"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Af"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Af"</item>
- <item msgid="4195153527464162486">"64 K per logbuffer"</item>
- <item msgid="7464037639415220106">"256 K per logbuffer"</item>
- <item msgid="8539423820514360724">"1 M per logbuffer"</item>
- <item msgid="1984761927103140651">"4 M per logbuffer"</item>
- <item msgid="7892098981256010498">"16 M per logbuffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Af"</item>
<item msgid="6014837961827347618">"Alles"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index d76a8a1..6f4f72a 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Skep tans nuwe gebruiker …"</string>
<string name="user_nickname" msgid="262624187455825083">"Bynaam"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Voeg gas by"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Beëindig gastesessie"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gas"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Neem \'n foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Kies \'n prent"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF (diensverskaffer-wi-fi)"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiele data is af"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nie gestel om data te gebruik nie"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Geen foon nie."</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 18696b1..e941c11 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"፣ ገቢር (ሚዲያ)"</item>
<item msgid="5001852592115448348">"፣ ገቢር (ስልክ)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ጠፍቷል"</item>
- <item msgid="7839165897132179888">"64 ኪባ"</item>
- <item msgid="2715700596495505626">"256 ኪባ"</item>
- <item msgid="7099386891713159947">"1 ሜባ"</item>
- <item msgid="6069075827077845520">"4 ሜባ"</item>
- <item msgid="8243549501764402572">"16 ሜባ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ጠፍቷል"</item>
<item msgid="4064786181089783077">"64 ኪባ"</item>
<item msgid="3052710745383602630">"256 ኪባ"</item>
<item msgid="3691785423374588514">"1 ሜባ"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ጠፍቷል"</item>
- <item msgid="4195153527464162486">"64 ኪባ በምዝግብ ማስታወሻ ቋጥ"</item>
- <item msgid="7464037639415220106">"256 ኪባ በምዝግብ ማስታወሻ ቋጥ"</item>
- <item msgid="8539423820514360724">"1 ሜ በምዝግብ ማስታወሻ ቋጥ"</item>
- <item msgid="1984761927103140651">"4 ሜ በምዝግብ ማስታወሻ ቋጥ"</item>
- <item msgid="7892098981256010498">"16 ሜ በምዝግብ ማስታወሻ ቋጥ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ጠፍቷል"</item>
<item msgid="6014837961827347618">"ሁሉም"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 85b5bc2..3f5df34 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"አዲስ ተጠቃሚ በመፍጠር ላይ…"</string>
<string name="user_nickname" msgid="262624187455825083">"ቅጽል ስም"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"እንግዳን አክል"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"የእንግዳ ክፍለ-ጊዜ ጨርስ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"እንግዳ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ፎቶ አንሳ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ምስል ይምረጡ"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ውሂብን ለመጠቀም አልተቀናበረም"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ምንም ስልክ የለም።"</string>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index d09b50e..db1d4b4 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"، مُفعَّل (وسائط)"</item>
<item msgid="5001852592115448348">"، مُفعَّل (هاتف)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"إيقاف"</item>
- <item msgid="7839165897132179888">"٦٤ كيلوبايت"</item>
- <item msgid="2715700596495505626">"٢٥٦ كيلوبايت"</item>
- <item msgid="7099386891713159947">"1 ميغابايت"</item>
- <item msgid="6069075827077845520">"٤ ميغابايت"</item>
- <item msgid="8243549501764402572">"١٦ ميغابايت"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"إيقاف"</item>
<item msgid="4064786181089783077">"٦٤ كيلوبايت"</item>
<item msgid="3052710745383602630">"٢٥٦ كيلوبايت"</item>
<item msgid="3691785423374588514">"1 ميغابايت"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"إيقاف"</item>
- <item msgid="4195153527464162486">"٦٤ كيلوبايت لكل ذاكرة تخزين مؤقت للتسجيل"</item>
- <item msgid="7464037639415220106">"٢٥٦ كيلوبايت لكل ذاكرة تخزين مؤقت للتسجيل"</item>
- <item msgid="8539423820514360724">"1 ميغابايت لكل ذاكرة تخزين مؤقت للتسجيل"</item>
- <item msgid="1984761927103140651">"٤ ميغابايت لكل ذاكرة تخزين مؤقت للتسجيل"</item>
- <item msgid="7892098981256010498">"١٦ ميغابايت لكل ذاكرة تخزين مؤقت للتسجيل"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"إيقاف"</item>
<item msgid="6014837961827347618">"الكل"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index f260559..0351d94 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -557,8 +557,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"جارٍ إنشاء مستخدم جديد…"</string>
<string name="user_nickname" msgid="262624187455825083">"اللقب"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"إضافة ضيف"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"إنهاء جلسة الضيف"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ضيف"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"التقاط صورة"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"اختيار صورة"</string>
@@ -581,6 +580,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"شبكة الجيل الرابع أو أحدث"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"تم إيقاف بيانات الجوال"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"لم يتم الضبط على استخدام البيانات"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ليست هناك إشارة بالهاتف."</string>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index b619d3b..b2494fb 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", সক্ৰিয় (মিডিয়া)"</item>
<item msgid="5001852592115448348">", সক্ৰিয় (ফ\'ন)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"অফ কৰক"</item>
- <item msgid="7839165897132179888">"৬৪কে."</item>
- <item msgid="2715700596495505626">"২৫৬কে."</item>
- <item msgid="7099386891713159947">"১মি."</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"১৬মি."</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"অফ কৰক"</item>
<item msgid="4064786181089783077">"৬৪কে."</item>
<item msgid="3052710745383602630">"২৫৬কে."</item>
<item msgid="3691785423374588514">"১মি."</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"অফ কৰক"</item>
- <item msgid="4195153527464162486">"প্ৰতিটো লগ বাফাৰত ৬৪কে."</item>
- <item msgid="7464037639415220106">"প্ৰতি লগ বাফাৰত 256K"</item>
- <item msgid="8539423820514360724">"প্ৰতিটো লগ বাফাৰত ১মি."</item>
- <item msgid="1984761927103140651">"প্ৰতিটো লগ বাফাৰত ৪মি."</item>
- <item msgid="7892098981256010498">"প্ৰতিটো লগ বাফাৰত ১৬মি."</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"অফ অৱস্থাত আছে"</item>
<item msgid="6014837961827347618">"সকলো"</item>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 32be72d..0f7db8f 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"এলটিই"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"এলটিই+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ম’বাইল ডেটা অফ অৱস্থাত আছে"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ডেটা ব্যৱহাৰ কৰিবলৈ ছেট কৰা নাই"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ফ\'নত ছিগনেল নাই৷"</string>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 55ec9d8..6ee2b8f 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktiv (media)"</item>
<item msgid="5001852592115448348">", aktiv (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Deaktiv"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Deaktiv"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Deaktiv"</item>
- <item msgid="4195153527464162486">"hər jurnal buferinə 64K"</item>
- <item msgid="7464037639415220106">"hər jurnal buferinə 256K"</item>
- <item msgid="8539423820514360724">"hər jurnal buferinə 1M"</item>
- <item msgid="1984761927103140651">"hər jurnal buferinə 4M"</item>
- <item msgid="7892098981256010498">"hər jurnal buferinə 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Deaktiv"</item>
<item msgid="6014837961827347618">"Bütün"</item>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 88e99ce..0855d17e 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Yeni istifadəçi yaradılır…"</string>
<string name="user_nickname" msgid="262624187455825083">"Ləqəb"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Qonaq əlavə edin"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Qonaq sessiyasını bitirin"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Qonaq"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Foto çəkin"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Şəkil seçin"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil data deaktivdir"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Data istifadə etmək üçün ayarlanmayıb"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Telefon yoxdur."</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 2926067..630ad7d 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktivan (medijski)"</item>
<item msgid="5001852592115448348">", aktivan (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Isključeno"</item>
- <item msgid="7839165897132179888">"64 kB"</item>
- <item msgid="2715700596495505626">"256 kB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Isključeno"</item>
<item msgid="4064786181089783077">"64 kB"</item>
<item msgid="3052710745383602630">"256 kB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Isključeno"</item>
- <item msgid="4195153527464162486">"64 kB po međumemoriji evidencije"</item>
- <item msgid="7464037639415220106">"256 kB po međumemoriji evidencije"</item>
- <item msgid="8539423820514360724">"1 MB po međumemoriji evidencije"</item>
- <item msgid="1984761927103140651">"4 MB po međumemoriji evidencije"</item>
- <item msgid="7892098981256010498">"16 MB po međumemoriji evidencije"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Isključeno"</item>
<item msgid="6014837961827347618">"Sve"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 4a820ea..3386fe86 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -554,8 +554,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Pravi se novi korisnik…"</string>
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Završi sesiju gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Slikaj"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string>
@@ -578,6 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"WiFi mobilnog operatera"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilni podaci su isključeni"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nije podešeno za korišćenje podataka"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefona."</string>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index af3a161..2d2c509 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", уключана (мультымедыя)"</item>
<item msgid="5001852592115448348">", уключана (тэлефон)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Выкл."</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Выкл."</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Выкл."</item>
- <item msgid="4195153527464162486">"64K на буфер журнала"</item>
- <item msgid="7464037639415220106">"256K на буфер журнала"</item>
- <item msgid="8539423820514360724">"1M на буфер журнала"</item>
- <item msgid="1984761927103140651">"4M на буфер журнала"</item>
- <item msgid="7892098981256010498">"16M на буфер журнала"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Выключана"</item>
<item msgid="6014837961827347618">"Усе"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 6a16246..6ac2172 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ствараецца новы карыстальнік…"</string>
<string name="user_nickname" msgid="262624187455825083">"Псеўданім"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Дадаць госця"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Завяршыць гасцявы сеанс"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Госць"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Зрабіць фота"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Выбраць відарыс"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мабільная перадача даных выключана"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Не зададзена для выкарыстання даных"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Няма тэлефона."</string>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 1b25bed..482ec22 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"– активно (мултимедия)"</item>
<item msgid="5001852592115448348">"– активно (телефон)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Изключено"</item>
- <item msgid="7839165897132179888">"64 КБ"</item>
- <item msgid="2715700596495505626">"256 КБ"</item>
- <item msgid="7099386891713159947">"1 МБ"</item>
- <item msgid="6069075827077845520">"4 МБ"</item>
- <item msgid="8243549501764402572">"16 МБ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Изключено"</item>
<item msgid="4064786181089783077">"64 КБ"</item>
<item msgid="3052710745383602630">"256 КБ"</item>
<item msgid="3691785423374588514">"1 МБ"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Изключено"</item>
- <item msgid="4195153527464162486">"Рег. буфер – 64 КБ"</item>
- <item msgid="7464037639415220106">"Рег. буфер – 256 КБ"</item>
- <item msgid="8539423820514360724">"Рег. буфер – 1 МБ"</item>
- <item msgid="1984761927103140651">"Рег. буфер – 4 МБ"</item>
- <item msgid="7892098981256010498">"Рег. буфер – 16 МБ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Изкл."</item>
<item msgid="6014837961827347618">"Всички"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 07ba66a..19ed5bd 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилните данни са изключени"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Не е зададено да използва данни"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Няма телефон."</string>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index 34cbc8f..2da3076 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", চালু আছে (মিডিয়া)"</item>
<item msgid="5001852592115448348">", চালু আছে (ফোন)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"বন্ধ আছে"</item>
- <item msgid="7839165897132179888">"৬৪K"</item>
- <item msgid="2715700596495505626">"২৫৬K"</item>
- <item msgid="7099386891713159947">"১M"</item>
- <item msgid="6069075827077845520">"৪M"</item>
- <item msgid="8243549501764402572">"১৬M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"বন্ধ আছে"</item>
<item msgid="4064786181089783077">"৬৪K"</item>
<item msgid="3052710745383602630">"২৫৬K"</item>
<item msgid="3691785423374588514">"১M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"বন্ধ আছে"</item>
- <item msgid="4195153527464162486">"লগ বাফার প্রতি ৬৪K"</item>
- <item msgid="7464037639415220106">"লগ বাফার প্রতি ২৫৬K"</item>
- <item msgid="8539423820514360724">"লগ বাফার প্রতি ১M"</item>
- <item msgid="1984761927103140651">"লগ বাফার প্রতি ৪M"</item>
- <item msgid="7892098981256010498">"লগ বাফার প্রতি ১৬M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"বন্ধ আছে"</item>
<item msgid="6014837961827347618">"সমস্ত"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 99ee1d6..b0e9342 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"নতুন ব্যবহারকারী তৈরি করা হচ্ছে…"</string>
<string name="user_nickname" msgid="262624187455825083">"বিশেষ নাম"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ করুন"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"গেস্ট সেশন শেষ করুন"</string>
<string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ফটো তুলুন"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"একটি ইমেজ বেছে নিন"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"মোবাইল ডেটা বন্ধ করা হয়েছে"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ডেটা ব্যবহার করার জন্য সেট করা নেই"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"কোনো ফোনের সংকেত নেই৷"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 6d2f1f3..b704385 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktivan (mediji)"</item>
<item msgid="5001852592115448348">", aktivan (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Isključeno"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Isključeno"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Isključeno"</item>
- <item msgid="4195153527464162486">"64K po međumemoriji zapisnika"</item>
- <item msgid="7464037639415220106">"256k po međumemoriji zapisnika"</item>
- <item msgid="8539423820514360724">"1M po međumemoriji zapisnika"</item>
- <item msgid="1984761927103140651">"4M po međumemoriji zapisnika"</item>
- <item msgid="7892098981256010498">"16M po međumemoriji zapisnika"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Isključeno"</item>
<item msgid="6014837961827347618">"Sve"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index eedad34..9377624 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -554,8 +554,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Kreiranje novog korisnika…"</string>
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Završi sesiju gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Snimite fotografiju"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberite sliku"</string>
@@ -578,6 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Prijenos podataka na mobilnoj mreži je isključen"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nije postavljeno za korištenje podataka"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefonskog signala."</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 4b24637..c9f63ab 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", actiu (contingut multimèdia)"</item>
<item msgid="5001852592115448348">", actiu (telèfon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"No"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"No"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"No"</item>
- <item msgid="4195153527464162486">"64 K / memòria intermèdia del registre"</item>
- <item msgid="7464037639415220106">"256 K / memòria intermèdia del registre"</item>
- <item msgid="8539423820514360724">"1 M / memòria intermèdia reg."</item>
- <item msgid="1984761927103140651">"4 M / memòria intermèdia del registre"</item>
- <item msgid="7892098981256010498">"16 M / memòria intermèdia del registre"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Desactivat"</item>
<item msgid="6014837961827347618">"Tot"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 209b2d6..a2a7770 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"S\'està creant l\'usuari…"</string>
<string name="user_nickname" msgid="262624187455825083">"Àlies"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Afegeix un convidat"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Finalitza la sessió de convidat"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidat"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fes una foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Tria una imatge"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"S\'han desactivat les dades mòbils"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"No s\'ha definit per utilitzar dades"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No hi ha senyal de telèfon."</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index 27dce16..556fc10 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktivní (média)"</item>
<item msgid="5001852592115448348">", aktivní (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Vypnuto"</item>
- <item msgid="7839165897132179888">"64 kB"</item>
- <item msgid="2715700596495505626">"256 kB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Vypnuto"</item>
<item msgid="4064786181089783077">"64 kB"</item>
<item msgid="3052710745383602630">"256 kB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Vypnuto"</item>
- <item msgid="4195153527464162486">"64 kB na vyrovnávací paměť protokolů"</item>
- <item msgid="7464037639415220106">"256 kB na vyrovnávací paměť protokolů"</item>
- <item msgid="8539423820514360724">"1 MB na vyrovnávací paměť protokolů"</item>
- <item msgid="1984761927103140651">"4 MB na vyrovnávací paměť protokolů"</item>
- <item msgid="7892098981256010498">"16 MB na vyrovnávací paměť protokolů"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Vypnuto"</item>
<item msgid="6014837961827347618">"Vše"</item>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index b3141e4..4db4d5c 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Vytváření nového uživatele…"</string>
<string name="user_nickname" msgid="262624187455825083">"Přezdívka"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Přidat hosta"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Ukončení relace hosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Host"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Pořídit fotku"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrat obrázek"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi operátora"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilní data jsou vypnuta"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nenastaveno k využití dat"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Žádná telefonní síť."</string>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index efe4150..69b8a09 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktiv (medier)"</item>
<item msgid="5001852592115448348">", aktiv (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Fra"</item>
- <item msgid="7839165897132179888">"64 kB"</item>
- <item msgid="2715700596495505626">"256 kB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Fra"</item>
<item msgid="4064786181089783077">"64 kB"</item>
<item msgid="3052710745383602630">"256 kB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Fra"</item>
- <item msgid="4195153527464162486">"64 kB pr. logbuffer"</item>
- <item msgid="7464037639415220106">"256 kB pr. logbuffer"</item>
- <item msgid="8539423820514360724">"1 MB pr. logbuffer"</item>
- <item msgid="1984761927103140651">"4 MB pr. logbuffer"</item>
- <item msgid="7892098981256010498">"16 MB pr. logbuffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Fra"</item>
<item msgid="6014837961827347618">"Alle"</item>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index a7fa91f..b76afa5c 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Opretter ny bruger…"</string>
<string name="user_nickname" msgid="262624187455825083">"Kaldenavn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Tilføj gæsten"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Afslut gæstesessionen"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gæst"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tag et billede"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Vælg et billede"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata er deaktiveret"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ikke indstillet til at anvende data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index e7c4887..f6e3496 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktiv (Medien)"</item>
<item msgid="5001852592115448348">", aktiv (Telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Aus"</item>
- <item msgid="7839165897132179888">"64.000"</item>
- <item msgid="2715700596495505626">"256.000"</item>
- <item msgid="7099386891713159947">"1 Mio."</item>
- <item msgid="6069075827077845520">"4 Mio."</item>
- <item msgid="8243549501764402572">"16 Mio."</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Aus"</item>
<item msgid="4064786181089783077">"64.000"</item>
<item msgid="3052710745383602630">"256.000"</item>
<item msgid="3691785423374588514">"1 Mio."</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Aus"</item>
- <item msgid="4195153527464162486">"64.000 pro Puffer"</item>
- <item msgid="7464037639415220106">"256.000 pro Puffer"</item>
- <item msgid="8539423820514360724">"1 Mio. pro Puffer"</item>
- <item msgid="1984761927103140651">"4 Mio. pro Puffer"</item>
- <item msgid="7892098981256010498">"16 Mio. pro Puffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Aus"</item>
<item msgid="6014837961827347618">"Alle"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 361b932..ba760dd 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Neuer Nutzer wird erstellt…"</string>
<string name="user_nickname" msgid="262624187455825083">"Alias"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Gast hinzufügen"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Gastsitzung beenden"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gast"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Foto machen"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Bild auswählen"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile Daten deaktiviert"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nicht für Datennutzung konfiguriert"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Kein Telefon"</string>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 838ca79..2fc7d0b 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ενεργή (μέσα)"</item>
<item msgid="5001852592115448348">", ενεργή (τηλέφωνο)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Ανενεργό"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Ανενεργό"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Ανενεργό"</item>
- <item msgid="4195153527464162486">"64 K ανά πρ. μν. αρχ. καταγρ."</item>
- <item msgid="7464037639415220106">"256 K ανά πρ. μν. αρχ. καταγρ."</item>
- <item msgid="8539423820514360724">"1 Μ ανά προσ. μν. αρχ. καταγρ."</item>
- <item msgid="1984761927103140651">"4 M ανά προσ. μν. αρχ. καταγρ."</item>
- <item msgid="7892098981256010498">"16 M ανά πρ. μν. αρχ. καταγρ."</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Ανενεργό"</item>
<item msgid="6014837961827347618">"Όλα"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index a3b3d26..c608a62 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Δημιουργία νέου χρήστη…"</string>
<string name="user_nickname" msgid="262624187455825083">"Ψευδώνυμο"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Προσθήκη επισκέπτη"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Λήξη περιόδου σύνδεσης επισκέπτη"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Επισκέπτης"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Λήψη φωτογραφίας"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Επιλογή εικόνας"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Τα δεδομένα κινητής τηλεφωνίας απενεργοποιήθηκαν"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Δεν ρυθμίστηκε ώστε να χρησιμοποιεί δεδομένα"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Δεν υπάρχει τηλέφωνο."</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index 6569f18..31dc7c9 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", active (media)"</item>
<item msgid="5001852592115448348">", active (phone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Off"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Off"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Off"</item>
- <item msgid="4195153527464162486">"64 K per log buffer"</item>
- <item msgid="7464037639415220106">"256 K per log buffer"</item>
- <item msgid="8539423820514360724">"1 M per log buffer"</item>
- <item msgid="1984761927103140651">"4 M per log buffer"</item>
- <item msgid="7892098981256010498">"16 M per log buffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Off"</item>
<item msgid="6014837961827347618">"All"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index fe7515f..e67c3d1 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 6569f18..31dc7c9 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", active (media)"</item>
<item msgid="5001852592115448348">", active (phone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Off"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Off"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Off"</item>
- <item msgid="4195153527464162486">"64 K per log buffer"</item>
- <item msgid="7464037639415220106">"256 K per log buffer"</item>
- <item msgid="8539423820514360724">"1 M per log buffer"</item>
- <item msgid="1984761927103140651">"4 M per log buffer"</item>
- <item msgid="7892098981256010498">"16 M per log buffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Off"</item>
<item msgid="6014837961827347618">"All"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 75a6678..b0830fc 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index 6569f18..31dc7c9 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", active (media)"</item>
<item msgid="5001852592115448348">", active (phone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Off"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Off"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Off"</item>
- <item msgid="4195153527464162486">"64 K per log buffer"</item>
- <item msgid="7464037639415220106">"256 K per log buffer"</item>
- <item msgid="8539423820514360724">"1 M per log buffer"</item>
- <item msgid="1984761927103140651">"4 M per log buffer"</item>
- <item msgid="7892098981256010498">"16 M per log buffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Off"</item>
<item msgid="6014837961827347618">"All"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index fe7515f..e67c3d1 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index 6569f18..31dc7c9 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", active (media)"</item>
<item msgid="5001852592115448348">", active (phone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Off"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Off"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Off"</item>
- <item msgid="4195153527464162486">"64 K per log buffer"</item>
- <item msgid="7464037639415220106">"256 K per log buffer"</item>
- <item msgid="8539423820514360724">"1 M per log buffer"</item>
- <item msgid="1984761927103140651">"4 M per log buffer"</item>
- <item msgid="7892098981256010498">"16 M per log buffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Off"</item>
<item msgid="6014837961827347618">"All"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index fe7515f..e67c3d1 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index cb702fe..e4322b9 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", active (media)"</item>
<item msgid="5001852592115448348">", active (phone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Off"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Off"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Off"</item>
- <item msgid="4195153527464162486">"64K per log buffer"</item>
- <item msgid="7464037639415220106">"256K per log buffer"</item>
- <item msgid="8539423820514360724">"1M per log buffer"</item>
- <item msgid="1984761927103140651">"4M per log buffer"</item>
- <item msgid="7892098981256010498">"16M per log buffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Off"</item>
<item msgid="6014837961827347618">"All"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index aed0800..4c0af75 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index cfce9b6..cf6ce2b 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", activo (contenido multimedia)"</item>
<item msgid="5001852592115448348">", activo (teléfono)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Desactivado"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Desactivado"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Desactivado"</item>
- <item msgid="4195153527464162486">"64 K/búfer registro"</item>
- <item msgid="7464037639415220106">"256 K/búfer registro"</item>
- <item msgid="8539423820514360724">"1 M/búfer registro"</item>
- <item msgid="1984761927103140651">"4 M/búfer registro"</item>
- <item msgid="7892098981256010498">"16 M/búfer registro"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Desactivado"</item>
<item msgid="6014837961827347618">"Todo"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index f9260a8..9ae7781 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Datos móviles desactivados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"No se configuró para usar datos"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sin teléfono"</string>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 5682dd5..37f91b2 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", activo (contenido multimedia)"</item>
<item msgid="5001852592115448348">", activo (teléfono)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Desactivado"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Desactivado"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Desactivado"</item>
- <item msgid="4195153527464162486">"64 K/búfer registro"</item>
- <item msgid="7464037639415220106">"256 K/búfer registro"</item>
- <item msgid="8539423820514360724">"1 M/búfer registro"</item>
- <item msgid="1984761927103140651">"4 M/búfer registro"</item>
- <item msgid="7892098981256010498">"16 M/búfer registro"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Desactivado"</item>
<item msgid="6014837961827347618">"Todo"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index bc17623..203726a 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Datos desactiv."</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"No está establecido para usar los datos"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sin teléfono"</string>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 9015cfe..537ea7a 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktiivne (meedia)"</item>
<item msgid="5001852592115448348">", aktiivne (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Väljas"</item>
- <item msgid="7839165897132179888">"64 000"</item>
- <item msgid="2715700596495505626">"256 000"</item>
- <item msgid="7099386891713159947">"1 000 000"</item>
- <item msgid="6069075827077845520">"4 000 000"</item>
- <item msgid="8243549501764402572">"16 000 000"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Väljas"</item>
<item msgid="4064786181089783077">"64 000"</item>
<item msgid="3052710745383602630">"256 000"</item>
<item msgid="3691785423374588514">"1 000 000"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Väljas"</item>
- <item msgid="4195153527464162486">"64 000 / logipuhver"</item>
- <item msgid="7464037639415220106">"256 000 / logipuhver"</item>
- <item msgid="8539423820514360724">"1 000 000 / logipuhver"</item>
- <item msgid="1984761927103140651">"4 000 000 / logipuhver"</item>
- <item msgid="7892098981256010498">"16 000 000 / logipuhver"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Väljas"</item>
<item msgid="6014837961827347618">"Kõik"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index c73f136..379ed6c 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Uue kasutaja loomine …"</string>
<string name="user_nickname" msgid="262624187455825083">"Hüüdnimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Lõpeta külastajaseanss"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Külaline"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Pildistage"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Valige pilt"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiilne andmeside on väljas"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ei ole andmeside kasutamiseks seadistatud"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Telefonisignaal puudub"</string>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 0e94bba..367d31c 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktibo (multimedia-edukia)"</item>
<item msgid="5001852592115448348">", aktibo (telefonoa)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Desaktibatuta"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Desaktibatuta"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Desaktibatuta"</item>
- <item msgid="4195153527464162486">"64 K erregistroen bufferreko"</item>
- <item msgid="7464037639415220106">"256 K erregistroen bufferreko"</item>
- <item msgid="8539423820514360724">"1 M erregistroen bufferreko"</item>
- <item msgid="1984761927103140651">"4 M erregistroen bufferreko"</item>
- <item msgid="7892098981256010498">"16 M erregistroen bufferreko"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Desaktibatuta"</item>
<item msgid="6014837961827347618">"Guztiak"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 2f51ac0..2582854 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Desaktibatuta dago datu-konexioa"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ez dago ezarrita datuak erabiltzeko"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ez dago telefono-zenbakirik."</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 075f7e0..070c8ec 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"، فعال (رسانه)"</item>
<item msgid="5001852592115448348">"، فعال (تلفن)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"خاموش"</item>
- <item msgid="7839165897132179888">"۶۴ هزار"</item>
- <item msgid="2715700596495505626">"۲۵۶ هزار"</item>
- <item msgid="7099386891713159947">"۱ میلیون"</item>
- <item msgid="6069075827077845520">"۴ میلیون"</item>
- <item msgid="8243549501764402572">"۱۶ میلیون"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"خاموش"</item>
<item msgid="4064786181089783077">"۶۴ هزار"</item>
<item msgid="3052710745383602630">"۲۵۶ هزار"</item>
<item msgid="3691785423374588514">"۱ میلیون"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"خاموش"</item>
- <item msgid="4195153527464162486">"۶۴ هزار در هر بافر گزارش"</item>
- <item msgid="7464037639415220106">"۲۵۶ هزار در هر بافر گزارش"</item>
- <item msgid="8539423820514360724">"۱ میلیون در هر بافر گزارش"</item>
- <item msgid="1984761927103140651">"۴ میلیون در هر بافر گزارش"</item>
- <item msgid="7892098981256010498">"۱۶ میلیون در هر بافر گزارش"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"خاموش"</item>
<item msgid="6014837961827347618">"همه"</item>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 038b815..cb598e5 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"درحال ایجاد کاربر جدید…"</string>
<string name="user_nickname" msgid="262624187455825083">"نام مستعار"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"افزودن مهمان"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"پایان دادن به جلسه مهمان"</string>
<string name="guest_nickname" msgid="6332276931583337261">"مهمان"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"عکس گرفتن"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"انتخاب تصویر"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"داده تلفن همراه خاموش است"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"برای استفاده از داده تنظیم نشده است"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"بدون تلفن."</string>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index d233c56..6c38cdf 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktiivinen (media)"</item>
<item msgid="5001852592115448348">", aktiivinen (puhelin)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Ei päällä"</item>
- <item msgid="7839165897132179888">"64 kt"</item>
- <item msgid="2715700596495505626">"256 kt"</item>
- <item msgid="7099386891713159947">"1 Mt"</item>
- <item msgid="6069075827077845520">"4 Mt"</item>
- <item msgid="8243549501764402572">"16 Mt"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Ei päällä"</item>
<item msgid="4064786181089783077">"64 kt"</item>
<item msgid="3052710745383602630">"256 kt"</item>
<item msgid="3691785423374588514">"1 Mt"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Ei päällä"</item>
- <item msgid="4195153527464162486">"64 kt / lokipuskuri"</item>
- <item msgid="7464037639415220106">"256 kt / lokipuskuri"</item>
- <item msgid="8539423820514360724">"1 Mt / lokipuskuri"</item>
- <item msgid="1984761927103140651">"4 Mt / lokipuskuri"</item>
- <item msgid="7892098981256010498">"16 Mt / lokipuskuri"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Ei päällä"</item>
<item msgid="6014837961827347618">"Kaikki"</item>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 33b6142..31dfe18 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Luodaan uutta käyttäjää…"</string>
<string name="user_nickname" msgid="262624187455825083">"Lempinimi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lisää vieras"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Lopeta Vierailija-käyttökerta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Vieras"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ota kuva"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Valitse kuva"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Operaattorin Wi-Fi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiilidata poistettu käytöstä"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ei käytä dataa"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ei puhelinverkkoyhteyttä."</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 1db6540..8d48047 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", actif (média)"</item>
<item msgid="5001852592115448348">", actif (téléphone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Désactivé"</item>
- <item msgid="7839165897132179888">"64 ko"</item>
- <item msgid="2715700596495505626">"256 ko"</item>
- <item msgid="7099386891713159947">"1 Mo"</item>
- <item msgid="6069075827077845520">"4 Mo"</item>
- <item msgid="8243549501764402572">"16 Mo"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Désactivé"</item>
<item msgid="4064786181089783077">"64 ko"</item>
<item msgid="3052710745383602630">"256 ko"</item>
<item msgid="3691785423374588514">"1 Mo"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Désactivé"</item>
- <item msgid="4195153527464162486">"64 ko/tampon journal"</item>
- <item msgid="7464037639415220106">"256 Ko/tampon journal"</item>
- <item msgid="8539423820514360724">"1 Mo/tampon journal"</item>
- <item msgid="1984761927103140651">"4 Mo/tampon journal"</item>
- <item msgid="7892098981256010498">"16 Mo/tampon journal"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Désactivé"</item>
<item msgid="6014837961827347618">"Tous"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 01492c2..e24c130 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -226,7 +226,7 @@
<string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Code d\'association Wi-Fi"</string>
<string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Échec de l\'association"</string>
<string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Vérifier que l\'appareil est connecté au même réseau."</string>
- <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Associer un appareil par Wi-Fi en numérisant un code QR"</string>
+ <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Associez l\'appareil par Wi-Fi en numérisant un code QR"</string>
<string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Association de l\'appareil en cours…"</string>
<string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Échec de l\'association de l\'appareil Soit le code QR est incorrect, soit l\'appareil n\'est pas connecté au même réseau."</string>
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresse IP et port"</string>
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Désactivées"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Non configuré pour l\'utilisation des données cellulaires"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Aucun signal"</string>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 7660925..d65ba69 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", actif (son des médias)"</item>
<item msgid="5001852592115448348">", actif (téléphone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Désactivé"</item>
- <item msgid="7839165897132179888">"64 Ko"</item>
- <item msgid="2715700596495505626">"256 Ko"</item>
- <item msgid="7099386891713159947">"1 Mo"</item>
- <item msgid="6069075827077845520">"4 Mo"</item>
- <item msgid="8243549501764402572">"16 Mo"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Désactivé"</item>
<item msgid="4064786181089783077">"64 Ko"</item>
<item msgid="3052710745383602630">"256 Ko"</item>
<item msgid="3691785423374588514">"1 Mo"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Désactivé"</item>
- <item msgid="4195153527464162486">"64 Ko par tampon journal"</item>
- <item msgid="7464037639415220106">"256 Ko par tampon journal"</item>
- <item msgid="8539423820514360724">"1 Mo par tampon journal"</item>
- <item msgid="1984761927103140651">"4 Mo par tampon journal"</item>
- <item msgid="7892098981256010498">"16 Mo par tampon journal"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Désactivé"</item>
<item msgid="6014837961827347618">"Tous"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 04ed5fe..a79ed0c 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Création d\'un nouvel utilisateur…"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Fermer la session Invité"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invité"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Prendre une photo"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Choisir une image"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Désactivées"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Non configuré pour utiliser les données"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Aucun signal"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 98f2072..f13eaae 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", activo (contido multimedia)"</item>
<item msgid="5001852592115448348">", activo (teléfono)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Desactivado"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Desactivado"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Desactivado"</item>
- <item msgid="4195153527464162486">"64 K por búfer de rexistro"</item>
- <item msgid="7464037639415220106">"256 K por búfer de rexistro"</item>
- <item msgid="8539423820514360724">"1 M por búfer de rexistro"</item>
- <item msgid="1984761927103140651">"4 M por búfer de rexistro"</item>
- <item msgid="7892098981256010498">"16 M por búfer de rexistro"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Desactivado"</item>
<item msgid="6014837961827347618">"Todo"</item>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index b59395c..97662a6 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creando usuario novo…"</string>
<string name="user_nickname" msgid="262624187455825083">"Alcume"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Engadir convidado"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Finalizar sesión de invitado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escoller imaxe"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Operador de wifi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Os datos móbiles están desactivados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Non se configurou para utilizar datos"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sen teléfono"</string>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index 1a3bf98..0bbd4f6 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", સક્રિય (મીડિયા)"</item>
<item msgid="5001852592115448348">", સક્રિય (ફોન)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"બંધ"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"બંધ"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"બંધ"</item>
- <item msgid="4195153527464162486">"લૉગ બફર દીઠ 64K"</item>
- <item msgid="7464037639415220106">"લૉગ બફર દીઠ 256K"</item>
- <item msgid="8539423820514360724">"લૉગ બફર દીઠ 1M"</item>
- <item msgid="1984761927103140651">"લૉગ બફર દીઠ 4M"</item>
- <item msgid="7892098981256010498">"લૉગ બફર દીઠ 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"બંધ"</item>
<item msgid="6014837961827347618">"તમામ"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 601ffde..46bd71b 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"નવા વપરાશકર્તા બનાવી રહ્યાં છીએ…"</string>
<string name="user_nickname" msgid="262624187455825083">"ઉપનામ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"અતિથિ ઉમેરો"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"અતિથિ સત્ર સમાપ્ત કરો"</string>
<string name="guest_nickname" msgid="6332276931583337261">"અતિથિ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ફોટો લો"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"છબી પસંદ કરો"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"મોબાઇલ ડેટા બંધ છે"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ડેટાનો ઉપયોગ કરવાનું સેટ કર્યું નથી"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"કોઈ ફોન નથી."</string>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 36b16e6..ace8b4a 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", चालू है (सिर्फ़ मीडिया के लिए)"</item>
<item msgid="5001852592115448348">", चालू है (सिर्फ़ फ़ोन के लिए)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"बंद"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"बंद"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"बंद"</item>
- <item msgid="4195153527464162486">"64K प्रति लॉग बफ़र"</item>
- <item msgid="7464037639415220106">"256K प्रति लॉग बफ़र"</item>
- <item msgid="8539423820514360724">"1 एमबी प्रति लॉग बफ़र"</item>
- <item msgid="1984761927103140651">"4M प्रति लॉग बफ़र"</item>
- <item msgid="7892098981256010498">"16M प्रति लॉग बफ़र"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"बंद"</item>
<item msgid="6014837961827347618">"सभी"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 974d00c..9cae311 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"एलटीई"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा बंद है"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा इस्तेमाल करने के लिए सेट नहीं किया गया है"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"कोई फ़ोन नहीं."</string>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 82a1e4a..c4188bf 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktivno (mediji)"</item>
<item msgid="5001852592115448348">", aktivno (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Isključeno"</item>
- <item msgid="7839165897132179888">"64 KB"</item>
- <item msgid="2715700596495505626">"256 KB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Isključeno"</item>
<item msgid="4064786181089783077">"64 KB"</item>
<item msgid="3052710745383602630">"256 KB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Isključeno"</item>
- <item msgid="4195153527464162486">"64 KB po međusprem. zapisnika"</item>
- <item msgid="7464037639415220106">"256 KB po međusprem. zapisnika"</item>
- <item msgid="8539423820514360724">"1 MB po međusprem. zapisnika"</item>
- <item msgid="1984761927103140651">"4 MB po međusprem. zapisnika"</item>
- <item msgid="7892098981256010498">"16 MB po međusprem. zapisnika"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Isključeno"</item>
<item msgid="6014837961827347618">"Sve"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index f792428..83bb2d1 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -554,8 +554,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Izrada novog korisnika…"</string>
<string name="user_nickname" msgid="262624187455825083">"Nadimak"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodavanje gosta"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Završi gostujuću sesiju"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografiraj"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string>
@@ -578,6 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G i više"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilni su podaci isključeni"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nije postavljeno za upotrebu podataka"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefona."</string>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index d043af0..cc36c18 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktív (média)"</item>
<item msgid="5001852592115448348">", aktív (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Ki"</item>
- <item msgid="7839165897132179888">"64 KB"</item>
- <item msgid="2715700596495505626">"256 KB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Ki"</item>
<item msgid="4064786181089783077">"64 KB"</item>
<item msgid="3052710745383602630">"256 KB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Ki"</item>
- <item msgid="4195153527464162486">"64 KB/naplópuffer"</item>
- <item msgid="7464037639415220106">"256 KB/naplópuffer"</item>
- <item msgid="8539423820514360724">"1 MB/naplópuffer"</item>
- <item msgid="1984761927103140651">"4 MB/naplópuffer"</item>
- <item msgid="7892098981256010498">"16 MB/naplópuffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Kikapcsolva"</item>
<item msgid="6014837961827347618">"Összes"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 2bf5325..9f184c7 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Új felhasználó létrehozása…"</string>
<string name="user_nickname" msgid="262624187455825083">"Becenév"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Vendég hozzáadása"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"A vendég munkamenet befejezése"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Vendég"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotó készítése"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Kép kiválasztása"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Szolgáltatói Wi-Fi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiladatok kikapcsolva"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nincs beállítva az adathasználat"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nincs telefon."</string>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index a279872..76ed9bd 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ակտիվ է (մեդիա)"</item>
<item msgid="5001852592115448348">", ակտիվ է (հեռախոս)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Անջատված է"</item>
- <item msgid="7839165897132179888">"64ԿԲ"</item>
- <item msgid="2715700596495505626">"256ԿԲ"</item>
- <item msgid="7099386891713159947">"1ՄԲ"</item>
- <item msgid="6069075827077845520">"4ՄԲ"</item>
- <item msgid="8243549501764402572">"16ՄԲ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Անջատված է"</item>
<item msgid="4064786181089783077">"64ԿԲ"</item>
<item msgid="3052710745383602630">"256ԿԲ"</item>
<item msgid="3691785423374588514">"1ՄԲ"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Անջատված է"</item>
- <item msgid="4195153527464162486">"Բուֆեր՝ առավ. 64ԿԲ"</item>
- <item msgid="7464037639415220106">"Բուֆեր՝ առավ. 256ԿԲ"</item>
- <item msgid="8539423820514360724">"Բուֆեր՝ առավ. 1ՄԲ"</item>
- <item msgid="1984761927103140651">"Բուֆեր՝ առավ. 4ՄԲ"</item>
- <item msgid="7892098981256010498">"Բուֆեր՝ առավ. 16ՄԲ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Անջատված է"</item>
<item msgid="6014837961827347618">"Բոլորը"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index fea1e12..cd6cbf3 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Բջջային ինտերնետն անջատված է"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Բջջային ինտերնետն ըստ կանխադրման չի օգտագործվում"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Հեռախոս չկա:"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 3ab50cc..14e3313 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktif (media)"</item>
<item msgid="5001852592115448348">", aktif (ponsel)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Nonaktif"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Nonaktif"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Nonaktif"</item>
- <item msgid="4195153527464162486">"64 K/buffer log"</item>
- <item msgid="7464037639415220106">"256 K/buffer log"</item>
- <item msgid="8539423820514360724">"1 M/buffer log"</item>
- <item msgid="1984761927103140651">"4 M/buffer log"</item>
- <item msgid="7892098981256010498">"16 M/buffer log"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Nonaktif"</item>
<item msgid="6014837961827347618">"Semua"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 7298cea..3b80918 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Membuat pengguna baru …"</string>
<string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Tambahkan tamu"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Akhiri sesi tamu"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Tamu"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ambil foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Pilih gambar"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Kuota nonaktif"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Tidak disetel untuk menggunakan data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Tidak dapat melakukan panggilan."</string>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 93274e4..7c1773b 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", virkt (hljóð- og myndefni)"</item>
<item msgid="5001852592115448348">", virkt (sími)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Slökkt"</item>
- <item msgid="7839165897132179888">"64 k"</item>
- <item msgid="2715700596495505626">"256 k"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Slökkt"</item>
<item msgid="4064786181089783077">"64 k"</item>
<item msgid="3052710745383602630">"256 k"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Slökkt"</item>
- <item msgid="4195153527464162486">"64 k/biðminni"</item>
- <item msgid="7464037639415220106">"256 k/biðminni"</item>
- <item msgid="8539423820514360724">"1 M/biðminni"</item>
- <item msgid="1984761927103140651">"4 M/biðminni"</item>
- <item msgid="7892098981256010498">"16 M/biðminni"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Slökkt"</item>
<item msgid="6014837961827347618">"Allt"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index bf6c031..ce9e665 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Stofnar nýjan notanda…"</string>
<string name="user_nickname" msgid="262624187455825083">"Gælunafn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Bæta gesti við"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Ljúka gestalotu"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gestur"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Taka mynd"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Velja mynd"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi símafyrirtækis (CWF)"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Slökkt á farsímagögnum"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ekki stillt á að nota gögn"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ekkert símasamband."</string>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 57c0c9b..127903f 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", attivo (contenuti multimediali)"</item>
<item msgid="5001852592115448348">", attivo (telefono)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Off"</item>
- <item msgid="7839165897132179888">"64 kB"</item>
- <item msgid="2715700596495505626">"256 kB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Off"</item>
<item msgid="4064786181089783077">"64 kB"</item>
<item msgid="3052710745383602630">"256 kB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Off"</item>
- <item msgid="4195153527464162486">"64 kB/buffer log"</item>
- <item msgid="7464037639415220106">"256 kB/buffer log"</item>
- <item msgid="8539423820514360724">"1 MB/buffer log"</item>
- <item msgid="1984761927103140651">"4 MB/buffer log"</item>
- <item msgid="7892098981256010498">"16 MB/buffer log"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Off"</item>
<item msgid="6014837961827347618">"Tutti"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 2ed92e4..93b24a0 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creazione nuovo utente…"</string>
<string name="user_nickname" msgid="262624187455825083">"Nickname"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Aggiungi ospite"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Termina sessione Ospite"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Ospite"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Scatta una foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Scegli un\'immagine"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi operatore"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Dati mobili disattivati"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Non impostato per l\'utilizzo dei dati"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nessun telefono."</string>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index fa53ab8..151b825 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", פעיל (מדיה)"</item>
<item msgid="5001852592115448348">", פעיל (טלפון)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"כבוי"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"כבוי"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"כבוי"</item>
- <item msgid="4195153527464162486">"64K לכל מאגר של יומן רישום"</item>
- <item msgid="7464037639415220106">"256K לכל מאגר של יומן רישום"</item>
- <item msgid="8539423820514360724">"1M לכל מאגר של יומן רישום"</item>
- <item msgid="1984761927103140651">"4M לכל מאגר של יומן רישום"</item>
- <item msgid="7892098981256010498">"16M לכל מאגר של יומן רישום"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"כבוי"</item>
<item msgid="6014837961827347618">"הכול"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index bf4c35e..ab67809 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"בתהליך יצירה של משתמש חדש…"</string>
<string name="user_nickname" msgid="262624187455825083">"כינוי"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"הוספת אורח"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"הפסקת הגלישה כאורח"</string>
<string name="guest_nickname" msgid="6332276931583337261">"אורח"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"צילום תמונה"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"לבחירת תמונה"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"+4G"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"+LTE"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi של הספק"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"חבילת הגלישה כבויה"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"לא מוגדרת לשימוש בנתונים"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"אין טלפון."</string>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 7a4e71b..1401069 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"、有効(メディア)"</item>
<item msgid="5001852592115448348">"、有効(スマートフォン)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"OFF"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"OFF"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"OFF"</item>
- <item msgid="4195153527464162486">"64 K / ログバッファ"</item>
- <item msgid="7464037639415220106">"256 K / ログバッファ"</item>
- <item msgid="8539423820514360724">"1 M / ログバッファ"</item>
- <item msgid="1984761927103140651">"4 M / ログバッファ"</item>
- <item msgid="7892098981256010498">"16 M / ログバッファ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"OFF"</item>
<item msgid="6014837961827347618">"すべて"</item>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index f467c60..3105e98 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -576,6 +576,8 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
+ <skip />
<string name="cell_data_off_content_description" msgid="2280700839891636498">"モバイルデータ OFF"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"データを使用するように設定されていません"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"電波状態:なし"</string>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index 935cc46..62ae1e6 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", აქტიური (მედია)"</item>
<item msgid="5001852592115448348">", აქტიური (ტელეფონი)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"გამორთული"</item>
- <item msgid="7839165897132179888">"64 კბაიტი"</item>
- <item msgid="2715700596495505626">"256 კბაიტი"</item>
- <item msgid="7099386891713159947">"1 მბაიტი"</item>
- <item msgid="6069075827077845520">"4 მბაიტი"</item>
- <item msgid="8243549501764402572">"16 მბაიტი"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"გამორთული"</item>
<item msgid="4064786181089783077">"64 კბაიტი"</item>
<item msgid="3052710745383602630">"256 კბაიტი"</item>
<item msgid="3691785423374588514">"1 მბაიტი"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"გამორთული"</item>
- <item msgid="4195153527464162486">"64 კბაიტი / ჟურნალის ბუფერი"</item>
- <item msgid="7464037639415220106">"256 კბაიტი / ჟურნალის ბუფერი"</item>
- <item msgid="8539423820514360724">"1 მბაიტი / ჟურნალის ბუფერი"</item>
- <item msgid="1984761927103140651">"4 მბაიტი / ჟურნალის ბუფერი"</item>
- <item msgid="7892098981256010498">"16 მბაიტი / ჟურნალის ბუფერი"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"გამორთული"</item>
<item msgid="6014837961827347618">"ყველა"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 493839f..0813305 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"მიმდინარეობს ახალი მომხმარებლის შექმნა…"</string>
<string name="user_nickname" msgid="262624187455825083">"მეტსახელი"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"სტუმრის დამატება"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"სტუმრის სესიის დასრულება"</string>
<string name="guest_nickname" msgid="6332276931583337261">"სტუმარი"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ფოტოს გადაღება"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"აირჩიეთ სურათი"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"მობილური ინტერნეტი გამორთულია"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"არ არის დაყენებული მონაცემების გამოყენებისთვის"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ტელეფონი არ არის."</string>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index faa8af8..a2fe014 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", қосулы (медиамазмұн)"</item>
<item msgid="5001852592115448348">", қосулы (телефон)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Өшірулі"</item>
- <item msgid="7839165897132179888">"64 КБ"</item>
- <item msgid="2715700596495505626">"256 КБ"</item>
- <item msgid="7099386891713159947">"1 МБ"</item>
- <item msgid="6069075827077845520">"4 МБ"</item>
- <item msgid="8243549501764402572">"16 МБ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Өшірулі"</item>
<item msgid="4064786181089783077">"64 КБ"</item>
<item msgid="3052710745383602630">"256 КБ"</item>
<item msgid="3691785423374588514">"1 МБ"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Өшірулі"</item>
- <item msgid="4195153527464162486">"Әр журнал буферіне 64 КБ"</item>
- <item msgid="7464037639415220106">"Әр журнал буферіне 256 КБ"</item>
- <item msgid="8539423820514360724">"Әр журнал буферіне 1 МБ"</item>
- <item msgid="1984761927103140651">"Әр журнал буферіне 4 МБ"</item>
- <item msgid="7892098981256010498">"Әр журнал буферіне 16 МБ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Өшірулі"</item>
<item msgid="6014837961827347618">"Барлығы"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 83d859b..16ee9c0 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -359,7 +359,7 @@
<string name="enable_gpu_debug_layers" msgid="4986675516188740397">"GPU жөндеу қабаттарын қосу"</string>
<string name="enable_gpu_debug_layers_summary" msgid="4921521407377170481">"GPU жөндеу қабаттарының жүктелуіне рұқсат ету"</string>
<string name="enable_verbose_vendor_logging" msgid="1196698788267682072">"Жеткізушілерді журналға тіркеу"</string>
- <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Қате туралы есепте қызмет көрсетушінің құрылғыға қатысты қосымша ақпаратын қамту. Мұнда жеке ақпарат көрсетілуі, батарея шығыны артуы және/немесе қосымша жад пайдаланылуы мүмкін."</string>
+ <string name="enable_verbose_vendor_logging_summary" msgid="5426292185780393708">"Қате туралы есепте жеткізушінің құрылғыға қатысты қосымша ақпараты қамтылады. Мұнда жеке ақпарат көрсетілуі, батарея шығыны артуы және/немесе қосымша жад пайдаланылуы мүмкін."</string>
<string name="window_animation_scale_title" msgid="5236381298376812508">"Терезе анимациясының өлшемі"</string>
<string name="transition_animation_scale_title" msgid="1278477690695439337">"Ауысу анимациясының өлшемі"</string>
<string name="animator_duration_scale_title" msgid="7082913931326085176">"Аниматор ұзақтығы"</string>
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Жаңа пайдаланушы профилі жасалуда…"</string>
<string name="user_nickname" msgid="262624187455825083">"Лақап ат"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Қонақты енгізу"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Қонақ сеансын аяқтау"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Қонақ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Фотосуретке түсіру"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Сурет таңдау"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобильдік деректер өшірулі"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Деректерді пайдалануға реттелмеген."</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Телефон жоқ."</string>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index 6f4589e..70c1e33 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"សកម្ម (មេឌៀ)"</item>
<item msgid="5001852592115448348">"សកម្ម (ទូរសព្ទ)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"បិទ"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"បិទ"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"បិទ"</item>
- <item msgid="4195153527464162486">"64K per log buffer"</item>
- <item msgid="7464037639415220106">"256K per log buffer"</item>
- <item msgid="8539423820514360724">"1M per log buffer"</item>
- <item msgid="1984761927103140651">"4M per log buffer"</item>
- <item msgid="7892098981256010498">"16M per log buffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"បិទ"</item>
<item msgid="6014837961827347618">"ទាំងអស់"</item>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index db571d6..5b47381 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"កំពុងបង្កើតអ្នកប្រើប្រាស់ថ្មី…"</string>
<string name="user_nickname" msgid="262624187455825083">"ឈ្មោះហៅក្រៅ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"បញ្ចូលភ្ញៀវ"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"បញ្ចប់វគ្គភ្ញៀវ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ភ្ញៀវ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ថតរូប"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ជ្រើសរើសរូបភាព"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ទិន្នន័យទូរសព្ទចល័តបានបិទ"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"មិនបានកំណត់ឱ្យប្រើទិន្នន័យទេ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"គ្មានទូរស័ព្ទ។"</string>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 7e543dd..1bfcdc0 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ಸಕ್ರಿಯ (ಮಾಧ್ಯಮ)"</item>
<item msgid="5001852592115448348">", ಸಕ್ರಿಯ (ಫೋನ್)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ಆಫ್"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ಆಫ್"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ಆಫ್"</item>
- <item msgid="4195153527464162486">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್ಗೆ 64K"</item>
- <item msgid="7464037639415220106">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್ಗೆ 256K"</item>
- <item msgid="8539423820514360724">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್ಗೆ 1M"</item>
- <item msgid="1984761927103140651">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್ಗೆ 4M"</item>
- <item msgid="7892098981256010498">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್ಗೆ 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ಆಫ್"</item>
<item msgid="6014837961827347618">"ಎಲ್ಲಾ"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 2e8b9f1..fd63dcb 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="user_nickname" msgid="262624187455825083">"ಅಡ್ಡ ಹೆಸರು"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ಅತಿಥಿಯನ್ನು ಸೇರಿಸಿ"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"ಅತಿಥಿ ಸೆಷನ್ ಅಂತ್ಯಗೊಳಿಸಿ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ಅತಿಥಿ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ಫೋಟೋ ತೆಗೆದುಕೊಳ್ಳಿ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ಚಿತ್ರವನ್ನು ಆರಿಸಿ"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ಡೇಟಾ ಬಳಸಲು ಹೊಂದಿಸಲಾಗಿಲ್ಲ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ಯಾವುದೇ ಫೋನ್ ಇಲ್ಲ."</string>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 9a18c16..648188f 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", 활성(미디어)"</item>
<item msgid="5001852592115448348">", 활성(휴대전화)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"사용 안함"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"사용 안함"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"사용 안함"</item>
- <item msgid="4195153527464162486">"로그 버퍼당 64K"</item>
- <item msgid="7464037639415220106">"로그 버퍼당 256K"</item>
- <item msgid="8539423820514360724">"로그 버퍼당 1M"</item>
- <item msgid="1984761927103140651">"로그 버퍼당 4M"</item>
- <item msgid="7892098981256010498">"로그 버퍼당 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"사용 안함"</item>
<item msgid="6014837961827347618">"전체"</item>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 0294e9d..a9c3f31 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"새로운 사용자를 만드는 중…"</string>
<string name="user_nickname" msgid="262624187455825083">"닉네임"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"게스트 추가"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"게스트 세션 종료"</string>
<string name="guest_nickname" msgid="6332276931583337261">"게스트"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"사진 찍기"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"이미지 선택"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G 이상"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"모바일 데이터 꺼짐"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"데이터를 사용하도록 설정되지 않음"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"휴대전화의 신호가 없습니다."</string>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index f5e812d..295c174 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", жандырылган (аудио)"</item>
<item msgid="5001852592115448348">", жандырылган (телефон)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Өчүк"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Өчүк"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Өчүк"</item>
- <item msgid="4195153527464162486">"Буфер: 64КБ ашпашы керек"</item>
- <item msgid="7464037639415220106">"Буфер: 256КБ ашпашы керек"</item>
- <item msgid="8539423820514360724">"Буфер: 1М ашпашы керек"</item>
- <item msgid="1984761927103140651">"Буфер: 4М ашпашы керек"</item>
- <item msgid="7892098981256010498">"Буфер: 16М ашпашы керек"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Өчүк"</item>
<item msgid="6014837961827347618">"Бардыгы"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 0c73cf6..bc3656f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Жаңы колдонуучу түзүлүүдө…"</string>
<string name="user_nickname" msgid="262624187455825083">"Ылакап аты"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Конок кошуу"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Конок сеансын бүтүрүү"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Конок"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Сүрөткө тартуу"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Сүрөт тандаңыз"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилдик Интернет өчүрүлгөн"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Дайындарды колдонуу үчүн жөндөлгөн эмес"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Телефон сигналы жок."</string>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index a0fb2b8..c48eb3b 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ອອນລາຍ (ມີເດຍ)"</item>
<item msgid="5001852592115448348">", ອອນລາຍ (ໂທລະສັບ)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ປິດ"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ປິດ"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ປິດ"</item>
- <item msgid="4195153527464162486">"ບັບເຟີ 64K ຕໍ່ບັນທຶກ"</item>
- <item msgid="7464037639415220106">"ບັບເຟີ 256K ຕໍ່ບັນທຶກ"</item>
- <item msgid="8539423820514360724">"ບັບເຟີ 1M ຕໍ່ບັນທຶກ"</item>
- <item msgid="1984761927103140651">"ບັບເຟີ 4M ຕໍ່ບັນທຶກ"</item>
- <item msgid="7892098981256010498">"ບັບເຟີ 16M ຕໍ່ບັນທຶກ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ປິດ"</item>
<item msgid="6014837961827347618">"ທັງໝົດ"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index fbe814a..8408c93 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ກຳລັງສ້າງຜູ້ໃຊ້ໃໝ່…"</string>
<string name="user_nickname" msgid="262624187455825083">"ຊື່ຫຼິ້ນ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ເພີ່ມແຂກ"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"ສິ້ນສຸດເຊດຊັນແຂກ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ແຂກ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ຖ່າຍຮູບ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ເລືອກຮູບ"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ປິດອິນເຕີເນັດມືຖືແລ້ວ"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ບໍ່ໄດ້ຕັ້ງໃຫ້ໃຊ້ອິນເຕີເນັດ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ບໍ່ມີໂທລະສັບ."</string>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 90a77bf..48b69c8 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktyvus (medija)"</item>
<item msgid="5001852592115448348">", aktyvus (telefonas)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Išjungta"</item>
- <item msgid="7839165897132179888">"64 KB"</item>
- <item msgid="2715700596495505626">"256 KB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Išjungta"</item>
<item msgid="4064786181089783077">"64 KB"</item>
<item msgid="3052710745383602630">"256 KB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Išjungta"</item>
- <item msgid="4195153527464162486">"64 KB žurnalo buferis"</item>
- <item msgid="7464037639415220106">"256 KB žurnalo buferis"</item>
- <item msgid="8539423820514360724">"1 MB žurnalo buferis"</item>
- <item msgid="1984761927103140651">"4 MB žurnalo buferis"</item>
- <item msgid="7892098981256010498">"16 MB žurnalo buferis"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Išjungta"</item>
<item msgid="6014837961827347618">"Viskas"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index b3d8e17..1dcfcf7 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Kuriamas naujas naudotojas…"</string>
<string name="user_nickname" msgid="262624187455825083">"Slapyvardis"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pridėti svečią"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Baigti svečio sesiją"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Svečias"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografuoti"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Pasirinkti vaizdą"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiliojo ryšio duomenys išjungti"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nenustatyta naudoti duomenis"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nėra telefono."</string>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 5891727..81a3721 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktīva (multivide)"</item>
<item msgid="5001852592115448348">", aktīva (tālrunis)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Izslēgts"</item>
- <item msgid="7839165897132179888">"64 KB"</item>
- <item msgid="2715700596495505626">"256 KB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Izslēgts"</item>
<item msgid="4064786181089783077">"64 KB"</item>
<item msgid="3052710745383602630">"256 KB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Izslēgts"</item>
- <item msgid="4195153527464162486">"64 KB vienam žurnāla buferim"</item>
- <item msgid="7464037639415220106">"256 KB vienam žurnāla buferim"</item>
- <item msgid="8539423820514360724">"1 MB vienam žurnāla buferim"</item>
- <item msgid="1984761927103140651">"4 MB vienam žurnāla buferim"</item>
- <item msgid="7892098981256010498">"16 MB vienam žurnāla buferim"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Izslēgts"</item>
<item msgid="6014837961827347618">"Visi"</item>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 3c69e64..3d9b78a 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -554,8 +554,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Notiek jauna lietotāja izveide…"</string>
<string name="user_nickname" msgid="262624187455825083">"Segvārds"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pievienot viesi"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Beigt viesa sesiju"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Viesis"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Uzņemt fotoattēlu"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Izvēlēties attēlu"</string>
@@ -578,6 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilie dati izslēgti"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nav iestatīts datu lietošanai"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nav tālruņa."</string>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 388e280..90a97c7 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", активен (аудиосодржини)"</item>
<item msgid="5001852592115448348">", активен (телефон)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Исклучено"</item>
- <item msgid="7839165897132179888">"64.000"</item>
- <item msgid="2715700596495505626">"256.000"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Исклучено"</item>
<item msgid="4064786181089783077">"64.000"</item>
<item msgid="3052710745383602630">"256.000"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Исклучено"</item>
- <item msgid="4195153527464162486">"64 K/меѓумеморија"</item>
- <item msgid="7464037639415220106">"256 K/меѓумеморија"</item>
- <item msgid="8539423820514360724">"1 M/меѓумеморија"</item>
- <item msgid="1984761927103140651">"4 M/меѓумеморија"</item>
- <item msgid="7892098981256010498">"16 M/меѓумеморија"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Исклучено"</item>
<item msgid="6014837961827347618">"Сите"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index b909359..0674f11 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Се создава нов корисник…"</string>
<string name="user_nickname" msgid="262624187455825083">"Прекар"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додај гостин"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Заврши ја гостинската сесија"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гостин"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Фотографирајте"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Одберете слика"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi-Fi на операторот"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилниот интернет е исклучен"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Не е поставен да користи интернет"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Нема сигнал."</string>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index cb31d22..5ea0615 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", സജീവ (മീഡിയ)"</item>
<item msgid="5001852592115448348">", സജീവമായ (ഫോൺ)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ഓഫ്"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ഓഫ്"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ഓഫ്"</item>
- <item msgid="4195153527464162486">"ഓരോ ലോഗ് ബഫറിനും 64K"</item>
- <item msgid="7464037639415220106">"ഓരോ ലോഗ് ബഫറിനും 256K"</item>
- <item msgid="8539423820514360724">"ഓരോ ലോഗ് ബഫറിനും 1M"</item>
- <item msgid="1984761927103140651">"ഓരോ ലോഗ് ബഫറിനും 4M"</item>
- <item msgid="7892098981256010498">"ഓരോ ലോഗ് ബഫറിനും 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ഓഫ്"</item>
<item msgid="6014837961827347618">"എല്ലാം"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 8f83ee1..1455669 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -450,7 +450,7 @@
<string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
<string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
<string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി നില ഒപ്റ്റിമൈസ് ചെയ്യുന്നു"</string>
+ <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററിയുടെ ആയുസിനായി ഒപ്റ്റിമൈസ് ചെയ്യുന്നു"</string>
<string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string>
<string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string>
<string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string>
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"പുതിയ ഉപയോക്താവിനെ സൃഷ്ടിക്കുന്നു…"</string>
<string name="user_nickname" msgid="262624187455825083">"വിളിപ്പേര്"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"അതിഥിയെ ചേർക്കുക"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"അതിഥി സെഷൻ അവസാനിപ്പിക്കുക"</string>
<string name="guest_nickname" msgid="6332276931583337261">"അതിഥി"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ഒരു ഫോട്ടോ എടുക്കുക"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ഒരു ചിത്രം തിരഞ്ഞെടുക്കുക"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"മൊബൈൽ ഡാറ്റ ഓഫാണ്"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ഡാറ്റ ഉപയോഗിക്കുന്നതിന് സജ്ജീകരിച്ചിട്ടില്ല"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ഫോൺ സിഗ്നൽ ഒന്നുമില്ല."</string>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index 6a33b48..e58ff66 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", идэвхтэй (медиа)"</item>
<item msgid="5001852592115448348">", идэвхтэй (утас)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Идэвхгүй"</item>
- <item msgid="7839165897132179888">"64000"</item>
- <item msgid="2715700596495505626">"256000"</item>
- <item msgid="7099386891713159947">"1 сая"</item>
- <item msgid="6069075827077845520">"4 сая"</item>
- <item msgid="8243549501764402572">"16 сая"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Идэвхгүй"</item>
<item msgid="4064786181089783077">"64000"</item>
<item msgid="3052710745383602630">"256000"</item>
<item msgid="3691785423374588514">"1 сая"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Идэвхгүй"</item>
- <item msgid="4195153527464162486">"лог буфер бүрд 64K"</item>
- <item msgid="7464037639415220106">"лог буфер бүрд 256K"</item>
- <item msgid="8539423820514360724">"лог буфер бүрд 1M"</item>
- <item msgid="1984761927103140651">"лог буфер бүрд 4M"</item>
- <item msgid="7892098981256010498">"лог буфер бүрд 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Идэвхгүй"</item>
<item msgid="6014837961827347618">"Бүгд"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 8168b79..f13cb0b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобайл дата унтраалттай байна"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Дата ашиглахаар тохируулаагүй"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Утас байхгүй."</string>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 8abf290..aaf51b3 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", अॅक्टिव्ह (मीडिया)"</item>
<item msgid="5001852592115448348">", अॅक्टिव्ह (फोन)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"बंद"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"बंद"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"बंद"</item>
- <item msgid="4195153527464162486">"प्रति लॉग बफर 64K"</item>
- <item msgid="7464037639415220106">"प्रति लॉग बफर 256K"</item>
- <item msgid="8539423820514360724">"प्रति लॉग बफर 1M"</item>
- <item msgid="1984761927103140651">"प्रति लॉग बफर 4M"</item>
- <item msgid="7892098981256010498">"प्रति लॉग बफर 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"बंद"</item>
<item msgid="6014837961827347618">"सर्व"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index f47d8e0..f5be76e 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -168,7 +168,7 @@
<string name="tts_play_example_summary" msgid="634044730710636383">"उच्चार संश्लेषणाचे एक छोटेसे प्रात्यक्षिक प्ले करा"</string>
<string name="tts_install_data_title" msgid="1829942496472751703">"व्हॉइस डेटा इंस्टॉल करा"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"उच्चार संश्लेषणासाठी आवश्यक आवाज डेटा इंस्टॉल करा"</string>
- <string name="tts_engine_security_warning" msgid="3372432853837988146">"हे उच्चार संश्लेषण इंजिन पासवर्ड आणि क्रेडिट कार्ड नंबर यासारख्या वैयक्तिक मजकुरासह, बोलला जाणारा सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. हे <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजिनवरून येते. या उच्चार संश्लेषण इंजिनचा वापर सक्षम करायचा?"</string>
+ <string name="tts_engine_security_warning" msgid="3372432853837988146">"हे उच्चार संश्लेषण इंजीन पासवर्ड आणि क्रेडिट कार्ड नंबर यासारख्या वैयक्तिक मजकुरासह, बोलला जाणारा सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. हे <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> इंजीनवरून येते. या उच्चार संश्लेषण इंजीनचा वापर सक्षम करायचा?"</string>
<string name="tts_engine_network_required" msgid="8722087649733906851">"या भाषेस टेक्स्ट टू स्पीचसाठी एका नेटवर्क कनेक्शनची आवश्यकता आहे."</string>
<string name="tts_default_sample_string" msgid="6388016028292967973">"हे उच्चार संश्लेषणाचे एक उदाहरण आहे"</string>
<string name="tts_status_title" msgid="8190784181389278640">"डीफॉल्ट भाषा स्थिती"</string>
@@ -177,8 +177,8 @@
<string name="tts_status_not_supported" msgid="2702997696245523743">"<xliff:g id="LOCALE">%1$s</xliff:g> समर्थित नाही"</string>
<string name="tts_status_checking" msgid="8026559918948285013">"तपासत आहे..."</string>
<string name="tts_engine_settings_title" msgid="7849477533103566291">"<xliff:g id="TTS_ENGINE_NAME">%s</xliff:g> साठी सेटिंग्ज"</string>
- <string name="tts_engine_settings_button" msgid="477155276199968948">"इंजिन सेटिंग्ज लाँच करा"</string>
- <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"प्राधान्य इंजिन"</string>
+ <string name="tts_engine_settings_button" msgid="477155276199968948">"इंजीन सेटिंग्ज लाँच करा"</string>
+ <string name="tts_engine_preference_section_title" msgid="3861562305498624904">"प्राधान्य इंजीन"</string>
<string name="tts_general_section_title" msgid="8919671529502364567">"सामान्य"</string>
<string name="tts_reset_speech_pitch_title" msgid="7149398585468413246">"उच्चार पिच रीसेट करा"</string>
<string name="tts_reset_speech_pitch_summary" msgid="6822904157021406449">"डीफॉल्टवर मजकूर ज्या पिचवर बोलला जातो तो रीसेट करा."</string>
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"नवीन वापरकर्ता तयार करत आहे…"</string>
<string name="user_nickname" msgid="262624187455825083">"टोपणनाव"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथी जोडा"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"अतिथी सत्र संपवा"</string>
<string name="guest_nickname" msgid="6332276931583337261">"अतिथी"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"फोटो काढा"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"इमेज निवडा"</string>
@@ -577,6 +576,8 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"४G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
+ <skip />
<string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा बंद आहे"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा वापरण्यासाठी सेट केलेले नाही"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"कोणताही फोन नाही."</string>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 15fad67..d2fc10e 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktif (media)"</item>
<item msgid="5001852592115448348">", aktif (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Mati"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Mati"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Mati"</item>
- <item msgid="4195153527464162486">"64K per penimbal log"</item>
- <item msgid="7464037639415220106">"256K per penimbal log"</item>
- <item msgid="8539423820514360724">"1M per penimbal log"</item>
- <item msgid="1984761927103140651">"4M per penimbal log"</item>
- <item msgid="7892098981256010498">"16M per penimbal log"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Mati"</item>
<item msgid="6014837961827347618">"Semua"</item>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index fb2826f..9527793 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Data mudah alih dimatikan"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Tidak ditetapkan untuk menggunakan data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Tiada telefon."</string>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 90bac81..3c69335 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"၊ ဖွင့်ထားသည် (မီဒီယာ)"</item>
<item msgid="5001852592115448348">"၊ ဖွင့်ထားသည် (ဖုန်း)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ပိတ်ရန်"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ပိတ်ရန်"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ပိတ်ရန်"</item>
- <item msgid="4195153527464162486">"မှတ်တမ်းယာယီကြားခံနယ်တစ်ခုလျှင် 64K"</item>
- <item msgid="7464037639415220106">"မှတ်တမ်းယာယီကြားခံနယ်တစ်ခုလျှင် 256K"</item>
- <item msgid="8539423820514360724">"မှတ်တမ်းကြားခံနယ် တစ်ခုလျှင် 1M"</item>
- <item msgid="1984761927103140651">"မှတ်တမ်းယာယီကြားခံနယ်တစ်ခုလျှင် 4M"</item>
- <item msgid="7892098981256010498">"မှတ်တမ်းယာယီကြားခံနယ်တစ်ခုလျှင် 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ပိတ်ရန်"</item>
<item msgid="6014837961827347618">"အားလုံး"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index d98d442..1dcb3cf 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"အသုံးပြုသူအသစ် ပြုလုပ်နေသည်…"</string>
<string name="user_nickname" msgid="262624187455825083">"နာမည်ပြောင်"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ဧည့်သည့် ထည့်ရန်"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"ဧည့်သည်ဆက်ရှင်ကို အဆုံးသတ်ရန်"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ဧည့်သည်"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ဓာတ်ပုံရိုက်ရန်"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ပုံရွေးရန်"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"မိုဘိုင်းဒေတာ ပိတ်ထားသည်"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ဒေတာအသုံးပြုရန် သတ်မှတ်မထားပါ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ဖုန်းလိုင်းမရှိပါ။"</string>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 275018b..5e6ee65 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktiv (media)"</item>
<item msgid="5001852592115448348">", aktiv (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Av"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Av"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Av"</item>
- <item msgid="4195153527464162486">"64K per loggbuffer"</item>
- <item msgid="7464037639415220106">"256K per loggbuffer"</item>
- <item msgid="8539423820514360724">"1M per loggbuffer"</item>
- <item msgid="1984761927103140651">"4M per loggbuffer"</item>
- <item msgid="7892098981256010498">"16M per loggbuffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Av"</item>
<item msgid="6014837961827347618">"Alle"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 944c48e..13f69c1 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Oppretter en ny bruker …"</string>
<string name="user_nickname" msgid="262624187455825083">"Kallenavn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Avslutt gjesteøkten"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gjest"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ta et bilde"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Velg et bilde"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata er slått av"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ikke konfigurert til å bruke data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 5ee6353..c8b89c7 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", सक्रिय (मिडिया)"</item>
<item msgid="5001852592115448348">", सक्रिय (फोन)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"निष्क्रिय गर्नुहोस्"</item>
- <item msgid="7839165897132179888">"६४के"</item>
- <item msgid="2715700596495505626">"२५६के"</item>
- <item msgid="7099386891713159947">"१एम"</item>
- <item msgid="6069075827077845520">"४एम"</item>
- <item msgid="8243549501764402572">"१६एम"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"निष्क्रिय गर्नुहोस्"</item>
<item msgid="4064786181089783077">"६४के"</item>
<item msgid="3052710745383602630">"२५६के"</item>
<item msgid="3691785423374588514">"१एम"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"निष्क्रिय गर्नुहोस्"</item>
- <item msgid="4195153527464162486">"६४के प्रति लग बफर"</item>
- <item msgid="7464037639415220106">"२५६के प्रति लग बफर"</item>
- <item msgid="8539423820514360724">"१एम प्रति लग बफर"</item>
- <item msgid="1984761927103140651">"४एम प्रति लग बफर"</item>
- <item msgid="7892098981256010498">"१६एम प्रति लग बफर"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"निष्क्रिय"</item>
<item msgid="6014837961827347618">"सबै"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 9a0d2ed..5795cc9 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"नयाँ प्रयोगकर्ता बनाउँदै…"</string>
<string name="user_nickname" msgid="262624187455825083">"उपनाम"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"अतिथिको सत्र अन्त्य गर्नुहोस्"</string>
<string name="guest_nickname" msgid="6332276931583337261">"अतिथि"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"फोटो खिच्नुहोस्"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"कुनै फोटो छनौट गर्नुहोस्"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा निष्क्रिय छ"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा प्रयोग गर्ने गरी सेट गरिएन"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"फोन छैन्।"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index bfbbae0..a20db9d 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", actief (media)"</item>
<item msgid="5001852592115448348">", actief (telefoon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Uit"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Uit"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Uit"</item>
- <item msgid="4195153527464162486">"64 K per logbuffer"</item>
- <item msgid="7464037639415220106">"256 K per logbuffer"</item>
- <item msgid="8539423820514360724">"1 M per logbuffer"</item>
- <item msgid="1984761927103140651">"4 M per logbuffer"</item>
- <item msgid="7892098981256010498">"16 M per logbuffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Uit"</item>
<item msgid="6014837961827347618">"Alle"</item>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index a8e4fb5..718ce5d 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiele data uit"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Gebruik van gegevens is niet ingesteld"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Geen telefoonsignaal."</string>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 4a3d5d7..b7de25e 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ସକ୍ରିୟ (ମିଡିଆ)"</item>
<item msgid="5001852592115448348">", ସକ୍ରିୟ (ଫୋନ୍)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ବନ୍ଦ"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ବନ୍ଦ"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ବନ୍ଦ"</item>
- <item msgid="4195153527464162486">"64K ପିଛା ଲଗ୍ ବଫର୍"</item>
- <item msgid="7464037639415220106">"256K ଲଗ୍ ପ୍ରତି ବଫର୍"</item>
- <item msgid="8539423820514360724">"1M ପ୍ରତି ଲଗ୍ ବଫର୍"</item>
- <item msgid="1984761927103140651">"ଲଗ୍ ବଫର୍ ପ୍ରତି 4M"</item>
- <item msgid="7892098981256010498">"16M ଲଗ ପିଛା ବଫର୍"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ବନ୍ଦ"</item>
<item msgid="6014837961827347618">"ସମସ୍ତ"</item>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 306ef44..41e84f9 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -114,7 +114,7 @@
<string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"ଶ୍ରବଣ ଯନ୍ତ୍ର ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_pairing_accept" msgid="2054232610815498004">"ପେୟାର୍"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ପେୟାର୍"</string>
- <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
+ <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"ବାତିଲ୍ କରନ୍ତୁ"</string>
<string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"ପେୟାରିଂ ଫଳରେ ସଂଯୁକ୍ତ ଥିବା ବେଳେ ଆପଣଙ୍କ ସମ୍ପର୍କଗୁଡ଼ିକୁ ଏବଂ କଲ୍ର ଇତିବୃତିକୁ ଆକସେସ୍ ମଞ୍ଜୁର ହୁଏ।"</string>
<string name="bluetooth_pairing_error_message" msgid="6626399020672335565">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ ପେୟାର୍ କରିହେଲା ନାହିଁ।"</string>
<string name="bluetooth_pairing_pin_error_message" msgid="264422127613704940">"ଏକ ଭୁଲ୍ PIN କିମ୍ବା ପାସକୀ କାରଣରୁ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ସହ ପେୟାର୍ କରିପାରିଲା ନାହିଁ।"</string>
@@ -497,7 +497,7 @@
</plurals>
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"ଅଧିକ ସମୟ।"</string>
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"କମ୍ ସମୟ।"</string>
- <string name="cancel" msgid="5665114069455378395">"କ୍ୟାନ୍ସଲ୍"</string>
+ <string name="cancel" msgid="5665114069455378395">"ବାତିଲ୍"</string>
<string name="okay" msgid="949938843324579502">"ଠିକ୍ ଅଛି"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"ଚାଲୁ କରନ୍ତୁ"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" ଅନ୍ କରନ୍ତୁ"</string>
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା ତିଆରି କରାଯାଉଛି…"</string>
<string name="user_nickname" msgid="262624187455825083">"ଡାକନାମ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ଅତିଥି ଯୋଗ କରନ୍ତୁ"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"ଅତିଥି ସେସନ୍ ଶେଷ କରନ୍ତୁ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ଅତିଥି"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ଗୋଟିଏ ଫଟୋ ଉଠାନ୍ତୁ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ଏକ ଛବି ବାଛନ୍ତୁ"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ମୋବାଇଲ୍ ଡାଟା ବନ୍ଦ ଅଛି"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ବ୍ୟବହୃତ ଡାଟା ପାଇଁ ସେଟ୍ ହୋଇନାହିଁ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"କୌଣସି ଫୋନ୍ ନାହିଁ।"</string>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index d594f3b..c64ee76 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ਕਿਰਿਆਸ਼ੀਲ (ਮੀਡੀਆ)"</item>
<item msgid="5001852592115448348">", ਕਿਰਿਆਸ਼ੀਲ (ਫ਼ੋਨ)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ਬੰਦ"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ਬੰਦ"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ਬੰਦ"</item>
- <item msgid="4195153527464162486">"64K ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ"</item>
- <item msgid="7464037639415220106">"256K ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ"</item>
- <item msgid="8539423820514360724">"1M ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ"</item>
- <item msgid="1984761927103140651">"4M ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ"</item>
- <item msgid="7892098981256010498">"16M ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ਬੰਦ"</item>
<item msgid="6014837961827347618">"ਸਭ"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index e231a26..2ae7d71 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਇਆ ਜਾ ਰਿਹਾ ਹੈ…"</string>
<string name="user_nickname" msgid="262624187455825083">"ਉਪਨਾਮ"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"ਮਹਿਮਾਨ ਸ਼ਾਮਲ ਕਰੋ"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰੋ"</string>
<string name="guest_nickname" msgid="6332276931583337261">"ਮਹਿਮਾਨ"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ਇੱਕ ਫ਼ੋਟੋ ਖਿੱਚੋ"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ਕੋਈ ਚਿੱਤਰ ਚੁਣੋ"</string>
@@ -577,6 +576,8 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <!-- no translation found for data_connection_carrier_wifi (2250268321065848954) -->
+ <skip />
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ਡਾਟਾ ਵਰਤਣ ਲਈ ਸੈੱਟ ਨਹੀਂ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ।"</string>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index eb33323..e873b7e 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktywne (multimedia)"</item>
<item msgid="5001852592115448348">", aktywne (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Wył."</item>
- <item msgid="7839165897132179888">"64 KB"</item>
- <item msgid="2715700596495505626">"256 KB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Wył."</item>
<item msgid="4064786181089783077">"64 KB"</item>
<item msgid="3052710745383602630">"256 KB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Wył."</item>
- <item msgid="4195153527464162486">"64 KB/bufor dziennika"</item>
- <item msgid="7464037639415220106">"256 KB/bufor dziennika"</item>
- <item msgid="8539423820514360724">"1 MB/bufor dziennika"</item>
- <item msgid="1984761927103140651">"4 MB/bufor dziennika"</item>
- <item msgid="7892098981256010498">"16 MB/bufor dziennika"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Wyłączone"</item>
<item msgid="6014837961827347618">"Wszystkie"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index a62e9cc..a57e541 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Tworzę nowego użytkownika…"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gościa"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Kończenie sesji gościa"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gość"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Zrób zdjęcie"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Wybierz obraz"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Wyłączona"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nie skonfigurowano do transmisji danych"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Brak sygnału telefonu."</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 81285aa..c0dcec0 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ativo (mídia)"</item>
<item msgid="5001852592115448348">", ativo (telefone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Desativado"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Desativado"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Desativado"</item>
- <item msgid="4195153527464162486">"64 K/buffer de registro"</item>
- <item msgid="7464037639415220106">"256 K/buffer de registro"</item>
- <item msgid="8539423820514360724">"1 M/buffer de registro"</item>
- <item msgid="1984761927103140651">"4 M/buffer de registro"</item>
- <item msgid="7892098981256010498">"16 M/buffer de registro"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Desativado"</item>
<item msgid="6014837961827347618">"Todos"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index fe922c0..f24b52b 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Criando novo usuário…"</string>
<string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Encerrar sessão de visitante"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Sem configuração para uso de dados"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 019a5f6..de63257 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ativo (multimédia)"</item>
<item msgid="5001852592115448348">", ativo (telemóvel)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Desativado"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Desativado"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Desativado"</item>
- <item msgid="4195153527464162486">"64 K por buffer de registo"</item>
- <item msgid="7464037639415220106">"256 K por buffer de registo"</item>
- <item msgid="8539423820514360724">"1 M por buffer de registo"</item>
- <item msgid="1984761927103140651">"4 M por buffer de registo"</item>
- <item msgid="7892098981256010498">"16 M por buffer de registo"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Desativado"</item>
<item msgid="6014837961827347618">"Todos"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 5d1f880..42ad0fe 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"A criar novo utilizador…"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudónimo"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Terminar a sessão de convidado"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"WFO"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Não definido para utilizar dados"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 81285aa..c0dcec0 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ativo (mídia)"</item>
<item msgid="5001852592115448348">", ativo (telefone)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Desativado"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Desativado"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Desativado"</item>
- <item msgid="4195153527464162486">"64 K/buffer de registro"</item>
- <item msgid="7464037639415220106">"256 K/buffer de registro"</item>
- <item msgid="8539423820514360724">"1 M/buffer de registro"</item>
- <item msgid="1984761927103140651">"4 M/buffer de registro"</item>
- <item msgid="7892098981256010498">"16 M/buffer de registro"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Desativado"</item>
<item msgid="6014837961827347618">"Todos"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index fe922c0..f24b52b 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Criando novo usuário…"</string>
<string name="user_nickname" msgid="262624187455825083">"Apelido"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Encerrar sessão de visitante"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Sem configuração para uso de dados"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 48a3fa7..0fe0ef0 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", activ (media)"</item>
<item msgid="5001852592115448348">", activ (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Dezactivată"</item>
- <item msgid="7839165897132179888">"64 KB"</item>
- <item msgid="2715700596495505626">"256 KB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Dezactivată"</item>
<item msgid="4064786181089783077">"64 KB"</item>
<item msgid="3052710745383602630">"256 KB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Dezactivată"</item>
- <item msgid="4195153527464162486">"64 KB/mem. temporară de înregistrări în jurnal"</item>
- <item msgid="7464037639415220106">"256 KB/mem. temporară de înregistrări în jurnal"</item>
- <item msgid="8539423820514360724">"1 MB/mem. temporară de înregistrări în jurnal"</item>
- <item msgid="1984761927103140651">"4 MB/mem. temporară de înregistrări în jurnal"</item>
- <item msgid="7892098981256010498">"16 MB/mem. temporară de înregistrări în jurnal"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Dezactivată"</item>
<item msgid="6014837961827347618">"Toate"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 765f83a..0743fe9 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -554,8 +554,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Se creează un utilizator nou…"</string>
<string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Adăugați un invitat"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Încheiați sesiunea pentru invitați"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Invitat"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Faceți o fotografie"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Alegeți o imagine"</string>
@@ -578,6 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Rețeaua Wi‑Fi a operatorului"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Date mobile dezactivate"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nu este setat pentru a folosi datele"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nu există semnal pentru telefon."</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 5617aa6..84c3dc6 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", активно (A2DP)"</item>
<item msgid="5001852592115448348">", активно (HSP/HFP)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Отключено"</item>
- <item msgid="7839165897132179888">"64 КБ"</item>
- <item msgid="2715700596495505626">"256 КБ"</item>
- <item msgid="7099386891713159947">"1 МБ"</item>
- <item msgid="6069075827077845520">"4 МБ"</item>
- <item msgid="8243549501764402572">"16 МБ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Отключено"</item>
<item msgid="4064786181089783077">"64 КБ"</item>
<item msgid="3052710745383602630">"256 КБ"</item>
<item msgid="3691785423374588514">"1 МБ"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Отключено"</item>
- <item msgid="4195153527464162486">"Буфер: макс. 64 КБ"</item>
- <item msgid="7464037639415220106">"Буфер: макс. 256 КБ"</item>
- <item msgid="8539423820514360724">"Буфер: макс. 1 МБ"</item>
- <item msgid="1984761927103140651">"Буфер: макс. 4 МБ"</item>
- <item msgid="7892098981256010498">"Буфер: макс. 16 МБ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Отключено"</item>
<item msgid="6014837961827347618">"Все"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 98b3203..d19438a 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Создаем нового пользователя…"</string>
<string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Добавить аккаунт гостя"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Завершить гостевой сеанс"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гость"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Сделать снимок"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Выбрать фото"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобильный Интернет отключен"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Мобильный Интернет по умолчанию не используется."</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Сигнал телефонной сети отсутствует."</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index 01d0dd2..81d0bbb 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", ක්රියාකාරී (මාධ්ය)"</item>
<item msgid="5001852592115448348">", ක්රියාකාරී (දුරකථන)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ක්රියාවිරහිතය"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ක්රියාවිරහිතය"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ක්රියාවිරහිතය"</item>
- <item msgid="4195153527464162486">"ලොග අන්තරාවකට 64K"</item>
- <item msgid="7464037639415220106">"ලොග අන්තරාවකට 256K"</item>
- <item msgid="8539423820514360724">"ලොග අන්තරාවකට 1M"</item>
- <item msgid="1984761927103140651">"ලොග අන්තරාවකට 4M"</item>
- <item msgid="7892098981256010498">"ලොග අන්තරාවකට 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ක්රියාවිරහිතය"</item>
<item msgid="6014837961827347618">"සියලු"</item>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 087f1403..15fe8c8 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"නව පරිශීලක තනමින්…"</string>
<string name="user_nickname" msgid="262624187455825083">"අපනාමය"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"අමුත්තා එක් කරන්න"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"ආරාධිත සැසිය අවසන් කරන්න"</string>
<string name="guest_nickname" msgid="6332276931583337261">"අමුත්තා"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ඡායාරූපයක් ගන්න"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"රූපයක් තෝරන්න"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"ජංගම දත්ත ක්රියාවිරහිතයි"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"දත්ත භාවිත කිරීමට සකසා නැත"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"දුරකථනයක් නැත."</string>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 5dcf791..2826cb3 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktívne (médiá)"</item>
<item msgid="5001852592115448348">", aktívne (telefón)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Vypnuté"</item>
- <item msgid="7839165897132179888">"64 kB"</item>
- <item msgid="2715700596495505626">"256 kB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Vypnuté"</item>
<item msgid="4064786181089783077">"64 kB"</item>
<item msgid="3052710745383602630">"256 kB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Vypnuté"</item>
- <item msgid="4195153527464162486">"64 kB na vyrov. pamäť denníka"</item>
- <item msgid="7464037639415220106">"256 kB na vyrov. pamäť denníka"</item>
- <item msgid="8539423820514360724">"1 MB na vyrov. pam. denníka"</item>
- <item msgid="1984761927103140651">"4 MB na vyrov. pamäť denníka"</item>
- <item msgid="7892098981256010498">"16 MB na vyrov. pamäť denníka"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Vypnuté"</item>
<item msgid="6014837961827347618">"Všetko"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 858f017..ee53b7c 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Vytvára sa nový používateľ…"</string>
<string name="user_nickname" msgid="262624187455825083">"Prezývka"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Pridať hosťa"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Ukončiť reláciu hosťa"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Hosť"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Odfotiť"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrať obrázok"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Wi‑Fi operátora"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilné dáta sú vypnuté"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nie je nastavené na používanie dát"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Žiadna telefónna sieť."</string>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 7ba23af..26c6e6e 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktivno (predstavnost)"</item>
<item msgid="5001852592115448348">", aktivno (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Izklopljeno"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Izklopljeno"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Izklopljeno"</item>
- <item msgid="4195153527464162486">"64 K/medpomnilnik dnevnika"</item>
- <item msgid="7464037639415220106">"256 K/medpomnilnik dnevnika"</item>
- <item msgid="8539423820514360724">"1 M/medpomnilnik dnevnika"</item>
- <item msgid="1984761927103140651">"4 M/medpomnilnik dnevnika"</item>
- <item msgid="7892098981256010498">"16 M/medpomnilnik dnevnika"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Izklopljeno"</item>
<item msgid="6014837961827347618">"Vse"</item>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 2386b13..66d33a7 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ustvarjanje novega uporabnika …"</string>
<string name="user_nickname" msgid="262624187455825083">"Vzdevek"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Dodajanje gosta"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Končaj sejo gosta"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gost"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Fotografiranje"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Izberi sliko"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Omrežje Wi‑Fi operaterja"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Prenos podatkov v mobilnem omrežju je izklopljen"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Ni nastavljeno za uporabo prenosa podatkov"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ni telefona."</string>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index fccfc2f..3db2e6b 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktiv (media)"</item>
<item msgid="5001852592115448348">", aktiv (telefoni)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Joaktiv"</item>
- <item msgid="7839165897132179888">"64 mijë"</item>
- <item msgid="2715700596495505626">"256 mijë"</item>
- <item msgid="7099386891713159947">"1 milion"</item>
- <item msgid="6069075827077845520">"4 milionë"</item>
- <item msgid="8243549501764402572">"16 milionë"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Joaktiv"</item>
<item msgid="4064786181089783077">"64 mijë"</item>
<item msgid="3052710745383602630">"256 mijë"</item>
<item msgid="3691785423374588514">"1 milion"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Joaktiv"</item>
- <item msgid="4195153527464162486">"64 mijë/memorie regjistrimi"</item>
- <item msgid="7464037639415220106">"256 mijë/memorie regjistrimi"</item>
- <item msgid="8539423820514360724">"1 milion/memorie regjistrimi"</item>
- <item msgid="1984761927103140651">"4 milionë/memorie regjistrimi"</item>
- <item msgid="7892098981256010498">"16 milionë/memorie regjistrimi"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Joaktive"</item>
<item msgid="6014837961827347618">"Të gjitha"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 8d53b25..d5c0231 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Të dhënat celulare janë joaktive"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Nuk është caktuar të përdorë të dhënat"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Nuk ka telefon."</string>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 11b4b76..ec4da5a 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", активан (медијски)"</item>
<item msgid="5001852592115448348">", активан (телефон)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Искључено"</item>
- <item msgid="7839165897132179888">"64 kB"</item>
- <item msgid="2715700596495505626">"256 kB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Искључено"</item>
<item msgid="4064786181089783077">"64 kB"</item>
<item msgid="3052710745383602630">"256 kB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Искључено"</item>
- <item msgid="4195153527464162486">"64 kB по међумеморији евиденције"</item>
- <item msgid="7464037639415220106">"256 kB по међумеморији евиденције"</item>
- <item msgid="8539423820514360724">"1 MB по међумеморији евиденције"</item>
- <item msgid="1984761927103140651">"4 MB по међумеморији евиденције"</item>
- <item msgid="7892098981256010498">"16 MB по међумеморији евиденције"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Искључено"</item>
<item msgid="6014837961827347618">"Све"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 0b64a70..ce74b84 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -554,8 +554,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Прави се нови корисник…"</string>
<string name="user_nickname" msgid="262624187455825083">"Надимак"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додај госта"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Заврши сесију госта"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гост"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Сликај"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Одабери слику"</string>
@@ -578,6 +577,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"WiFi мобилног оператера"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилни подаци су искључени"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Није подешено за коришћење података"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Нема телефона."</string>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index be68c71..b631f44 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktiv (media)"</item>
<item msgid="5001852592115448348">", aktiv (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Av"</item>
- <item msgid="7839165897132179888">"64 kB"</item>
- <item msgid="2715700596495505626">"256 kB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Av"</item>
<item msgid="4064786181089783077">"64 kB"</item>
<item msgid="3052710745383602630">"256 kB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Av"</item>
- <item msgid="4195153527464162486">"64 kB/loggbuffert"</item>
- <item msgid="7464037639415220106">"256 kB/loggbuffert"</item>
- <item msgid="8539423820514360724">"1 MB/loggbuffert"</item>
- <item msgid="1984761927103140651">"4 MB/loggbuffert"</item>
- <item msgid="7892098981256010498">"16 MB/loggbuffert"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Av"</item>
<item msgid="6014837961827347618">"Alla"</item>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 58eda86..eacb7a8 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Skapar ny användare …"</string>
<string name="user_nickname" msgid="262624187455825083">"Smeknamn"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Lägg till gäst"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Avsluta gästsession"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Gäst"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Ta ett foto"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Välj en bild"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Operatörens Wi-Fi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata har inaktiverats"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Inte inställd på mobildata"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index da99b91..cd15e2c 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", inatumika (maudhui)"</item>
<item msgid="5001852592115448348">", inatumika (simu)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Imezimwa"</item>
- <item msgid="7839165897132179888">"K64"</item>
- <item msgid="2715700596495505626">"K256"</item>
- <item msgid="7099386891713159947">"M1"</item>
- <item msgid="6069075827077845520">"M4"</item>
- <item msgid="8243549501764402572">"M16"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Imezimwa"</item>
<item msgid="4064786181089783077">"K64"</item>
<item msgid="3052710745383602630">"K256"</item>
<item msgid="3691785423374588514">"M1"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Imezimwa"</item>
- <item msgid="4195153527464162486">"K64 kwa kila akiba ya kumbukumbu"</item>
- <item msgid="7464037639415220106">"K256 kwa kila akiba ya kumbukumbu"</item>
- <item msgid="8539423820514360724">"M1 kwa kila akiba ya kumbukumbu"</item>
- <item msgid="1984761927103140651">"M4 kwa kila akiba ya kumbukumbu"</item>
- <item msgid="7892098981256010498">"M16 kwa kila akiba ya kumbukumbu"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Yamezimwa"</item>
<item msgid="6014837961827347618">"Zote"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 889163b..e7045a7 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Inaweka mtumiaji mpya…"</string>
<string name="user_nickname" msgid="262624187455825083">"Jina wakilishi"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Weka mgeni"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Maliza kipindi cha mgeni"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Mgeni"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Piga picha"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Chagua picha"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Umezima data ya mtandao wa simu"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Haijawekewa mipangilio ya kutumia data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Hakuna simu"</string>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 1c55954..01b0a8e 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", செயலில் உள்ளது (மீடியா)"</item>
<item msgid="5001852592115448348">", செயலில் உள்ளது (மொபைல்)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ஆஃப்"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ஆஃப்"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ஆஃப்"</item>
- <item msgid="4195153527464162486">"64K / லாக் பஃபர்"</item>
- <item msgid="7464037639415220106">"256K / லாக் பஃபர்"</item>
- <item msgid="8539423820514360724">"1M / லாக் பஃபர்"</item>
- <item msgid="1984761927103140651">"4M / லாக் பஃபர்"</item>
- <item msgid="7892098981256010498">"16M / லாக் பஃபர்"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ஆஃப்"</item>
<item msgid="6014837961827347618">"எல்லாம்"</item>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index e0de778..06c7ccb 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"புதிய பயனரை உருவாக்குகிறது…"</string>
<string name="user_nickname" msgid="262624187455825083">"புனைப்பெயர்"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"கெஸ்ட்டைச் சேர்"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"விருந்தினர் அமர்வை நிறைவுசெய்"</string>
<string name="guest_nickname" msgid="6332276931583337261">"கெஸ்ட்"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"படமெடுங்கள்"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"படத்தைத் தேர்வுசெய்யுங்கள்"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"மொபைல் டேட்டா ஆஃப் செய்யப்பட்டது"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"தரவை உபயோகிக்க அமைக்கப்படவில்லை"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"சிக்னல் இல்லை."</string>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index e1c0406..4bdd55b 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", (మీడియా) సక్రియంగా ఉంది"</item>
<item msgid="5001852592115448348">", (ఫోన్) సక్రియంగా ఉంది"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ఆఫ్"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ఆఫ్"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ఆఫ్ చేయబడింది"</item>
- <item msgid="4195153527464162486">"లాగ్ బఫర్కి 64K"</item>
- <item msgid="7464037639415220106">"లాగ్ బఫర్కి 256K"</item>
- <item msgid="8539423820514360724">"లాగ్ బఫర్కి 1M"</item>
- <item msgid="1984761927103140651">"లాగ్ బఫర్కి 4M"</item>
- <item msgid="7892098981256010498">"లాగ్ బఫర్కి 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ఆఫ్ చేయి"</item>
<item msgid="6014837961827347618">"అన్నీ"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 53f4abf..897abea 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"కొత్త యూజర్ను క్రియేట్ చేస్తోంది…"</string>
<string name="user_nickname" msgid="262624187455825083">"మారుపేరు"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"అతిథిని జోడించండి"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"గెస్ట్ సెషన్ను ముగించు"</string>
<string name="guest_nickname" msgid="6332276931583337261">"అతిథి"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ఒక ఫోటో తీయండి"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ఇమేజ్ను ఎంచుకోండి"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"మొబైల్ డేటా ఆఫ్లో ఉంది"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"డేటాను ఉపయోగించే విధంగా సెట్ చేయలేదు"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ఫోన్ లేదు."</string>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 21fe6e4..9f6080b 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"ใช้งานอยู่ (สื่อ)"</item>
<item msgid="5001852592115448348">"ใช้งานอยู่ (โทรศัพท์)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"ปิด"</item>
- <item msgid="7839165897132179888">"64 K"</item>
- <item msgid="2715700596495505626">"256 K"</item>
- <item msgid="7099386891713159947">"1 M"</item>
- <item msgid="6069075827077845520">"4 M"</item>
- <item msgid="8243549501764402572">"16 M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"ปิด"</item>
<item msgid="4064786181089783077">"64 K"</item>
<item msgid="3052710745383602630">"256 K"</item>
<item msgid="3691785423374588514">"1 M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"ปิด"</item>
- <item msgid="4195153527464162486">"64 K ต่อบัฟเฟอร์ไฟล์บันทึก"</item>
- <item msgid="7464037639415220106">"256 K ต่อบัฟเฟอร์ไฟล์บันทึก"</item>
- <item msgid="8539423820514360724">"1 M ต่อบัฟเฟอร์ไฟล์บันทึก"</item>
- <item msgid="1984761927103140651">"4 M ต่อบัฟเฟอร์ไฟล์บันทึก"</item>
- <item msgid="7892098981256010498">"16 M ต่อบัฟเฟอร์ไฟล์บันทึก"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"ปิด"</item>
<item msgid="6014837961827347618">"ทั้งหมด"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 5f93563..6316452 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"เน็ตมือถือปิดอยู่"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ไม่ได้ตั้งค่าให้ใช้อินเทอร์เน็ตมือถือ"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"ไม่มีสัญญาณโทรศัพท์"</string>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 9f07cff..ab68a68 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", aktibo (media)"</item>
<item msgid="5001852592115448348">", aktibo (telepono)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"I-off"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"I-off"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"I-off"</item>
- <item msgid="4195153527464162486">"64K kada log buffer"</item>
- <item msgid="7464037639415220106">"256K kada log buffer"</item>
- <item msgid="8539423820514360724">"1M kada log buffer"</item>
- <item msgid="1984761927103140651">"4M kada log buffer"</item>
- <item msgid="7892098981256010498">"16M kada log buffer"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Naka-off"</item>
<item msgid="6014837961827347618">"Lahat"</item>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 9bbfb1d..0aabbe5 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Naka-off ang mobile data"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Hindi nakatakdang gumamit ng data"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Walang telepono."</string>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index fc90c9a..d5d578c 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", etkin (medya)"</item>
<item msgid="5001852592115448348">", etkin (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Kapalı"</item>
- <item msgid="7839165897132179888">"64 KB"</item>
- <item msgid="2715700596495505626">"256 KB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Kapalı"</item>
<item msgid="4064786181089783077">"64 KB"</item>
<item msgid="3052710745383602630">"256 KB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Kapalı"</item>
- <item msgid="4195153527464162486">"Günlük arabelleği başına 64 KB"</item>
- <item msgid="7464037639415220106">"Günlük arabelleği başına 256 KB"</item>
- <item msgid="8539423820514360724">"Günlük arabelleği başına 1 MB"</item>
- <item msgid="1984761927103140651">"Günlük arabelleği başına 4 MB"</item>
- <item msgid="7892098981256010498">"Günlük arabelleği başına 16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Kapalı"</item>
<item msgid="6014837961827347618">"Tümü"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 9dd32b6..44c8f13 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil veri kapalı"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Veri kullanmak üzere ayarlanmadı"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Telefon sinyali yok."</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 4405c37..41922a3 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", активний (лише для медіа)"</item>
<item msgid="5001852592115448348">", активний (лише для телефона)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Вимкнено"</item>
- <item msgid="7839165897132179888">"64 КБ"</item>
- <item msgid="2715700596495505626">"256 КБ"</item>
- <item msgid="7099386891713159947">"1 МБ"</item>
- <item msgid="6069075827077845520">"4 МБ"</item>
- <item msgid="8243549501764402572">"16 МБ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Вимкнено"</item>
<item msgid="4064786181089783077">"64 КБ"</item>
<item msgid="3052710745383602630">"256 КБ"</item>
<item msgid="3691785423374588514">"1 МБ"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Вимкнено"</item>
- <item msgid="4195153527464162486">"Буфер журналу: 64 КБ"</item>
- <item msgid="7464037639415220106">"Буфер журналу: 256 КБ"</item>
- <item msgid="8539423820514360724">"Буфер журналу: 1 МБ"</item>
- <item msgid="1984761927103140651">"Буфер журналу: 4 МБ"</item>
- <item msgid="7892098981256010498">"Буфер журналу: 16 МБ"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Вимкнено"</item>
<item msgid="6014837961827347618">"Усі"</item>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 99cc958..7851111 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -555,8 +555,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Створення нового користувача…"</string>
<string name="user_nickname" msgid="262624187455825083">"Псевдонім"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Додати гостя"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Завершити сеанс у режимі \"Гість\""</string>
<string name="guest_nickname" msgid="6332276931583337261">"Гість"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Зробити фотографію"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Вибрати зображення"</string>
@@ -579,6 +578,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"Мережа Wi-Fi оператора"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобільне передавання даних вимкнено"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Не вибрано для використання даних"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Немає сигналу телефону."</string>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index f4c2500..a3539ff 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">"، فعال (میڈیا)"</item>
<item msgid="5001852592115448348">"، فعال (فون)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"آف"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"آف"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"آف"</item>
- <item msgid="4195153527464162486">"64K فی لاگ بفر"</item>
- <item msgid="7464037639415220106">"256K فی لاگ بفر"</item>
- <item msgid="8539423820514360724">"1M فی لاگ بفر"</item>
- <item msgid="1984761927103140651">"4M فی لاگ بفر"</item>
- <item msgid="7892098981256010498">"16M فی لاگ بفر"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"آف"</item>
<item msgid="6014837961827347618">"تمام"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 515cf70..82783b3 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"نیا صارف تخلیق کرنا…"</string>
<string name="user_nickname" msgid="262624187455825083">"عرفی نام"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"مہمان کو شامل کریں"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"مہمان سیشن ختم کریں"</string>
<string name="guest_nickname" msgid="6332276931583337261">"مہمان"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"ایک تصویر لیں"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"ایک تصویر منتخب کریں"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"موبائل ڈیٹا آف ہے"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"ڈیٹا استعمال کرنے کے لیے سیٹ نہیں ہے"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"کوئی فون نہیں ہے۔"</string>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 0770dcc..e695e20 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", faol (media)"</item>
<item msgid="5001852592115448348">", faol (telefon)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Yoqilmagan"</item>
- <item msgid="7839165897132179888">"64 KB"</item>
- <item msgid="2715700596495505626">"256 KB"</item>
- <item msgid="7099386891713159947">"1 MB"</item>
- <item msgid="6069075827077845520">"4 MB"</item>
- <item msgid="8243549501764402572">"16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Yoqilmagan"</item>
<item msgid="4064786181089783077">"64 KB"</item>
<item msgid="3052710745383602630">"256 KB"</item>
<item msgid="3691785423374588514">"1 MB"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Yoqilmagan"</item>
- <item msgid="4195153527464162486">"Bufer: maks. 64 KB"</item>
- <item msgid="7464037639415220106">"Bufer: maks. 256 KB"</item>
- <item msgid="8539423820514360724">"Bufer: maks. 1 MB"</item>
- <item msgid="1984761927103140651">"Bufer: maks. 4 MB"</item>
- <item msgid="7892098981256010498">"Bufer: maks. 16 MB"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Yoqilmagan"</item>
<item msgid="6014837961827347618">"Hammasi"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 1830046..c2a96c6 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil internet yoqilmagan"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Maʼlumotlardan foydalanish uchun sozlanmagan"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Signal yo‘q."</string>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 635cf11..cac6c46 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", đang hoạt động (nội dung nghe nhìn)"</item>
<item msgid="5001852592115448348">", đang hoạt động (điện thoại)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Tắt"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Tắt"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Tắt"</item>
- <item msgid="4195153527464162486">"64K mỗi bộ đệm nhật ký"</item>
- <item msgid="7464037639415220106">"256K mỗi bộ đệm nhật ký"</item>
- <item msgid="8539423820514360724">"1M mỗi bộ đệm nhật ký"</item>
- <item msgid="1984761927103140651">"4M mỗi bộ đệm nhật ký"</item>
- <item msgid="7892098981256010498">"16M mỗi bộ đệm nhật ký"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Tắt"</item>
<item msgid="6014837961827347618">"Tất cả"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 2d56e45..2596424 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Đã tắt dữ liệu di động"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Chưa được đặt để sử dụng dữ liệu"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Không có điện thoại nào."</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 29d04e9..dc0ca10 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">",使用中(媒体)"</item>
<item msgid="5001852592115448348">",使用中(手机)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"关闭"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"关闭"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"关闭"</item>
- <item msgid="4195153527464162486">"每个日志缓冲区 64K"</item>
- <item msgid="7464037639415220106">"每个日志缓冲区 256K"</item>
- <item msgid="8539423820514360724">"每个日志缓冲区 1M"</item>
- <item msgid="1984761927103140651">"每个日志缓冲区 4M"</item>
- <item msgid="7892098981256010498">"每个日志缓冲区 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"关闭"</item>
<item msgid="6014837961827347618">"全部"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 6b64d27..60afd6d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -214,7 +214,7 @@
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用二维码配对设备"</string>
<string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"使用二维码扫描器配对新设备"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配对码配对设备"</string>
- <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位数验证码配对新设备"</string>
+ <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位数的配对码配对新设备"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"已配对的设备"</string>
<string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"当前已连接"</string>
<string name="adb_wireless_device_details_title" msgid="7129369670526565786">"设备详细信息"</string>
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"正在创建新用户…"</string>
<string name="user_nickname" msgid="262624187455825083">"昵称"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"添加访客"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"结束访客会话"</string>
<string name="guest_nickname" msgid="6332276931583337261">"访客"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"拍摄照片"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"选择图片"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"移动数据网络已关闭"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"未设置为使用移动数据"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"没有手机信号。"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index e7e2f84..cae08a6 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">",使用中 (媒體)"</item>
<item msgid="5001852592115448348">",使用中 (手機)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"關閉"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"關閉"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"關閉"</item>
- <item msgid="4195153527464162486">"每個記錄緩衝區 64K"</item>
- <item msgid="7464037639415220106">"每個記錄緩衝區 256K"</item>
- <item msgid="8539423820514360724">"每個記錄緩衝區 1M"</item>
- <item msgid="1984761927103140651">"每個記錄緩衝區 4M"</item>
- <item msgid="7892098981256010498">"每個記錄緩衝區 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"關閉"</item>
<item msgid="6014837961827347618">"全部"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 4ab580e..925f738 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -576,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"流動網絡供應商 Wi-Fi"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"流動數據已關閉"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"未設定至可使用資料"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"沒有電話訊號。"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index 0fdc14e..959d022 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">",使用中 (媒體)"</item>
<item msgid="5001852592115448348">",使用中 (手機)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"關閉"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"關閉"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"關閉"</item>
- <item msgid="4195153527464162486">"每個記錄緩衝區 64K"</item>
- <item msgid="7464037639415220106">"每個記錄緩衝區 256K"</item>
- <item msgid="8539423820514360724">"每個記錄緩衝區 1M"</item>
- <item msgid="1984761927103140651">"每個記錄緩衝區 4M"</item>
- <item msgid="7892098981256010498">"每個記錄緩衝區 16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"關閉"</item>
<item msgid="6014837961827347618">"全部"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 46695db..e40d351 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"正在建立新使用者…"</string>
<string name="user_nickname" msgid="262624187455825083">"暱稱"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"結束訪客工作階段"</string>
<string name="guest_nickname" msgid="6332276931583337261">"訪客"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"拍照"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"選擇圖片"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"行動數據已關閉"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"並未設為使用行動數據"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"沒有電話訊號。"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 2d43c67..78079e8 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -155,28 +155,14 @@
<item msgid="253388653486517049">", iyasebenza (imidiya)"</item>
<item msgid="5001852592115448348">", iyasebenza (ifoni)"</item>
</string-array>
- <string-array name="select_logd_size_titles">
- <item msgid="1191094707770726722">"Valiwe"</item>
- <item msgid="7839165897132179888">"64K"</item>
- <item msgid="2715700596495505626">"256K"</item>
- <item msgid="7099386891713159947">"1M"</item>
- <item msgid="6069075827077845520">"4M"</item>
- <item msgid="8243549501764402572">"16M"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_titles:5 (6078203297886482480) -->
<string-array name="select_logd_size_lowram_titles">
<item msgid="1145807928339101085">"Valiwe"</item>
<item msgid="4064786181089783077">"64K"</item>
<item msgid="3052710745383602630">"256K"</item>
<item msgid="3691785423374588514">"1M"</item>
</string-array>
- <string-array name="select_logd_size_summaries">
- <item msgid="409235464399258501">"Valiwe"</item>
- <item msgid="4195153527464162486">"64K ngebhafa yelogu ngayinye"</item>
- <item msgid="7464037639415220106">"256K ngebhafa yelogu ngayinye"</item>
- <item msgid="8539423820514360724">"1M ngebhafa yelogu ngayi"</item>
- <item msgid="1984761927103140651">"4M ngebhafa yelogu ngayinye"</item>
- <item msgid="7892098981256010498">"16M ngebhafa yelogu ngayinye"</item>
- </string-array>
+ <!-- no translation found for select_logd_size_summaries:5 (2983219471251787208) -->
<string-array name="select_logpersist_titles">
<item msgid="704720725704372366">"Valiwe"</item>
<item msgid="6014837961827347618">"Konke"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index f4ff6ec..c304c14 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -553,8 +553,7 @@
<string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Idala umsebenzisi omusha…"</string>
<string name="user_nickname" msgid="262624187455825083">"Isiteketiso"</string>
<string name="guest_new_guest" msgid="3482026122932643557">"Engeza isivakashi"</string>
- <!-- no translation found for guest_exit_guest (4754204715192830850) -->
- <skip />
+ <string name="guest_exit_guest" msgid="4754204715192830850">"Misa isikhathi sesihambeli"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Isihambeli"</string>
<string name="user_image_take_photo" msgid="467512954561638530">"Thatha isithombe"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Khetha isithombe"</string>
@@ -577,6 +576,7 @@
<string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
<string name="data_connection_lte" msgid="7675461204366364124">"I-LTE"</string>
<string name="data_connection_lte_plus" msgid="6643158654804916653">"I-LTE+"</string>
+ <string name="data_connection_carrier_wifi" msgid="2250268321065848954">"I-CWF"</string>
<string name="cell_data_off_content_description" msgid="2280700839891636498">"Idatha yeselula ivaliwe"</string>
<string name="not_default_data_content_description" msgid="6517068332106592887">"Akusethiwe ukuze kusetshenziswe idatha"</string>
<string name="accessibility_no_phone" msgid="2687419663127582503">"Ayikho ifoni."</string>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index c63cf06..2b5e9cd 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -291,7 +291,7 @@
<item>256K</item>
<item>1M</item>
<item>4M</item>
- <item>16M</item>
+ <item>8M</item>
</string-array>
<!-- Titles for logd limit size lowram selection preference. [CHAR LIMIT=14] -->
@@ -309,7 +309,7 @@
<item>262144</item>
<item>1048576</item>
<item>4194304</item>
- <item>16777216</item>
+ <item>8388608</item>
</string-array>
<!-- Summaries for logd limit size selection preference. [CHAR LIMIT=50]-->
@@ -319,7 +319,7 @@
<item>256K per log buffer</item>
<item>1M per log buffer</item>
<item>4M per log buffer</item>
- <item>16M per log buffer</item>
+ <item>8M per log buffer</item>
</string-array>
<!-- Values for logpersist state selection preference. -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 4614694..15bacbf 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -171,6 +171,10 @@
} else {
ssid = getValidSsid(mWifiInfo);
}
+ if (mProviderModel) {
+ isCarrierMerged = mWifiInfo.isCarrierMerged();
+ subId = mWifiInfo.getSubscriptionId();
+ }
updateRssi(mWifiInfo.getRssi());
maybeRequestNetworkScore();
}
@@ -211,6 +215,8 @@
private void updateWifiState() {
state = mWifiManager.getWifiState();
enabled = state == WifiManager.WIFI_STATE_ENABLED;
+ isCarrierMerged = false;
+ subId = 0;
}
private void updateRssi(int newRssi) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppPreferenceTest.java
similarity index 92%
rename from packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
rename to packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppPreferenceTest.java
index 2848888..9e265a4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppPreferenceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.widget.apppreference;
+package com.android.settingslib.widget;
import static com.google.common.truth.Truth.assertThat;
@@ -23,8 +23,6 @@
import androidx.preference.PreferenceViewHolder;
-import com.android.settingslib.widget.R;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 53e67e1..fbc71f1 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -264,7 +264,6 @@
VALIDATORS.put(Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.EMERGENCY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.EMERGENCY_GESTURE_SOUND_ENABLED, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Secure.EMERGENCY_GESTURE_CALL_NUMBER, NONE_NEGATIVE_LONG_VALIDATOR);
VALIDATORS.put(Secure.ADAPTIVE_CONNECTIVITY_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(
Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS, NONE_NEGATIVE_LONG_VALIDATOR);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index e22f264..07a5a44 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -742,7 +742,6 @@
Settings.Secure.SKIP_GESTURE,
Settings.Secure.SILENCE_GESTURE,
Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
- Settings.Secure.EMERGENCY_GESTURE_CALL_NUMBER,
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
Settings.Secure.FACE_UNLOCK_RE_ENROLL,
Settings.Secure.TAP_GESTURE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 14151191..41cc835 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -157,6 +157,7 @@
<uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" />
<uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" />
<uses-permission android:name="android.permission.MANAGE_SEARCH_UI" />
+ <uses-permission android:name="android.permission.MANAGE_SMARTSPACE" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.SET_TIME" />
@@ -369,8 +370,9 @@
<!-- Permissions required for CTS tests to close system dialogs -->
<uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" />
- <!-- Permission required for CTS test - HideOverlayWindowsTest -->
+ <!-- Permissions required for CTS test - HideOverlayWindowsTest -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+ <uses-permission android:name="android.permission.SYSTEM_APPLICATION_OVERLAY"/>
<!-- Permission required for CTS test - CtsHdmiCecHostTestCases -->
<uses-permission android:name="android.permission.HDMI_CEC" />
@@ -382,6 +384,9 @@
<!-- Permission required for CTS tests to enable/disable rate limiting toasts. -->
<uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" />
+ <!-- Permission required for CTS to test sensor privacy behavior -->
+ <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SimAppDialog/res/values-mn/strings.xml b/packages/SimAppDialog/res/values-mn/strings.xml
index f21b80b..51298bb 100644
--- a/packages/SimAppDialog/res/values-mn/strings.xml
+++ b/packages/SimAppDialog/res/values-mn/strings.xml
@@ -19,8 +19,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="8898068901680117589">"Sim аппын харилцах цонх"</string>
<string name="install_carrier_app_title" msgid="334729104862562585">"Мобайл үйлчилгээг идэвхжүүлэх"</string>
- <string name="install_carrier_app_description" msgid="4014303558674923797">"Та шинэ СИМ-ээ зөв ажиллуулахын тулд <xliff:g id="ID_1">%1$s</xliff:g> аппыг суулгах хэрэгтэй болно"</string>
- <string name="install_carrier_app_description_default" msgid="7356830245205847840">"Та шинэ СИМ-ээ зөв ажиллуулахын тулд оператор компанийхаа аппыг суулгах хэрэгтэй болно"</string>
+ <string name="install_carrier_app_description" msgid="4014303558674923797">"Та шинэ SIM-ээ зөв ажиллуулахын тулд <xliff:g id="ID_1">%1$s</xliff:g> аппыг суулгах хэрэгтэй болно"</string>
+ <string name="install_carrier_app_description_default" msgid="7356830245205847840">"Та шинэ SIM-ээ зөв ажиллуулахын тулд оператор компанийхаа аппыг суулгах хэрэгтэй болно"</string>
<string name="install_carrier_app_defer_action" msgid="2558576736886876209">"Одоо биш"</string>
<string name="install_carrier_app_download_action" msgid="7859229305958538064">"Апп татах"</string>
</resources>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 55bdebd..80c8a28 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -51,7 +51,6 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:gravity="center_horizontal"
- android:letterSpacing="0.03"
android:textColor="?attr/wallpaperTextColor"
android:singleLine="true"
style="@style/widget_title_bold"
@@ -72,12 +71,12 @@
android:id="@+id/animatable_clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="right"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center_horizontal"
android:textSize="100dp"
- android:letterSpacing="0.02"
- android:lineSpacingMultiplier=".8"
android:includeFontPadding="false"
android:fontFamily="@font/clock"
+ android:lineSpacingMultiplier=".65"
android:typeface="monospace"
android:elegantTextHeight="false"
dozeWeight="200"
@@ -97,9 +96,8 @@
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:textSize="@dimen/large_clock_text_size"
- android:letterSpacing="0.02"
- android:lineSpacingMultiplier=".8"
android:includeFontPadding="false"
+ android:lineSpacingMultiplier=".65"
android:fontFamily="@font/clock"
android:typeface="monospace"
android:elegantTextHeight="false"
diff --git a/packages/SystemUI/res/drawable/ic_camera_blocked.xml b/packages/SystemUI/res/drawable/ic_camera_blocked.xml
new file mode 100644
index 0000000..0161bcb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_camera_blocked.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="m18,12c-2.75,0 -5,2.25 -5,5 0,2.75 2.25,5 5,5 2.75,0 5,-2.25 5,-5 0,-2.75 -2.1667,-5 -5,-5zM15.5,17.8333h5v-1.6666h-5z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+ <path
+ android:pathData="m16.4,5.5004h-2.536l-1.464,-1.6H7.6l-1.464,1.6H3.6c-0.88,0 -1.6,0.72 -1.6,1.6v9.6c0,0.88 0.72,1.6 1.6,1.6h8.5413C12.0488,17.8817 12,17.4465 12,17c0,-0.1005 0.0025,-0.2004 0.0073,-0.2996H3.6V7.1004H16.4V11.2157C16.9094,11.0751 17.4459,11 18,11V7.1004c0,-0.88 -0.72,-1.6 -1.6,-1.6zM6.8,11.9004c0,-1.768 1.432,-3.2 3.2,-3.2 1.768,0 3.2,1.432 3.2,3.2 0,1.768 -1.432,3.2 -3.2,3.2 -1.768,0 -3.2,-1.432 -3.2,-3.2z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_mic_blocked.xml b/packages/SystemUI/res/drawable/ic_mic_blocked.xml
new file mode 100644
index 0000000..0ce7a58
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_mic_blocked.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ Copyright (C) 2021 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="m17,12c-2.75,0 -5,2.25 -5,5 0,2.75 2.25,5 5,5 2.75,0 5,-2.25 5,-5 0,-2.75 -2.1667,-5 -5,-5zM14.5,17.8333h5v-1.6666h-5z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+ <path
+ android:pathData="m12,12c0,1.66 -1.34,3 -3,3C7.34,15 6,13.66 6,12L6,6C6,4.34 7.34,3 9,3c1.66,0 3,1.34 3,3zM9,5C8.45,5 8,5.45 8,6v6c0,0.55 0.45,1 1,1 0.55,0 1,-0.45 1,-1L10,6C10,5.45 9.55,5 9,5ZM11.0147,16.577C10.3983,16.849 9.7167,17 9,17 6.24,17 4,14.76 4,12L2,12c0,3.53 2.61,6.43 6,6.92L8,22h2v-3.08c0.4212,-0.0609 0.8303,-0.1589 1.2238,-0.2908C11.078,18.1111 11,17.5647 11,17c0,-0.1422 0.0049,-0.2832 0.0147,-0.423z"
+ android:fillColor="#30302a"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml b/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml
new file mode 100644
index 0000000..3d6ca7a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_no_calling_sms.xml
@@ -0,0 +1,28 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10c0.34,0 0.68,-0.02 1.01,-0.05V20h-1v-0.04c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96H13v-2H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2H21.8C20.87,5.44 16.83,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56C16.43,5.07 17.96,6.35 18.92,8zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82C10.52,6.57 11.17,5.24 12,4.04zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2H4.26zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56C7.57,18.93 6.04,17.66 5.08,16zM8.03,8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8z"
+ android:fillAlpha="0.3"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,19.3v-0.9l-3.37,-2.25v-2.47C18.63,13.3 18.35,13 18,13s-0.63,0.3 -0.63,0.68v2.47L14,18.4v0.9l3.37,-1.12v2.48l-0.84,0.68V22L18,21.55L19.47,22v-0.67l-0.84,-0.68v-2.48L22,19.3z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_internet_airplane.xml b/packages/SystemUI/res/drawable/ic_qs_no_internet_airplane.xml
new file mode 100644
index 0000000..3d6ca7a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_no_internet_airplane.xml
@@ -0,0 +1,28 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10c0.34,0 0.68,-0.02 1.01,-0.05V20h-1v-0.04c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96H13v-2H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2H21.8C20.87,5.44 16.83,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56C16.43,5.07 17.96,6.35 18.92,8zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82C10.52,6.57 11.17,5.24 12,4.04zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2H4.26zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56C7.57,18.93 6.04,17.66 5.08,16zM8.03,8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8z"
+ android:fillAlpha="0.3"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,19.3v-0.9l-3.37,-2.25v-2.47C18.63,13.3 18.35,13 18,13s-0.63,0.3 -0.63,0.68v2.47L14,18.4v0.9l3.37,-1.12v2.48l-0.84,0.68V22L18,21.55L19.47,22v-0.67l-0.84,-0.68v-2.48L22,19.3z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_internet_available.xml b/packages/SystemUI/res/drawable/ic_qs_no_internet_available.xml
new file mode 100644
index 0000000..b7cd954
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_no_internet_available.xml
@@ -0,0 +1,31 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10c0.34,0 0.68,-0.02 1.01,-0.05V20h-1v-0.04c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96H13v-2H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2H21.8C20.87,5.44 16.83,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56C16.43,5.07 17.96,6.35 18.92,8zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82C10.52,6.57 11.17,5.24 12,4.04zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2H4.26zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56C7.57,18.93 6.04,17.66 5.08,16zM8.03,8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8z"
+ android:fillAlpha="0.3"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M16,14.75c0,-1.93 1.57,-3.5 3.5,-3.5s3.5,1.57 3.5,3.5c0,1.12 -0.69,1.73 -1.36,2.32c-0.64,0.56 -1.26,1.1 -1.26,2.06h-1.75c0,-1.59 0.82,-2.22 1.54,-2.78c0.57,-0.44 1.08,-0.83 1.08,-1.6c0,-0.96 -0.79,-1.75 -1.75,-1.75s-1.75,0.79 -1.75,1.75H16z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M18.63,20.25h1.75V22h-1.75V20.25z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_internet_unavailable.xml b/packages/SystemUI/res/drawable/ic_qs_no_internet_unavailable.xml
new file mode 100644
index 0000000..9fe2b10
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_no_internet_unavailable.xml
@@ -0,0 +1,28 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M2,12C2,6.48 6.47,2 11.99,2C17.52,2 22,6.48 22,12c0,0.34 -0.02,0.67 -0.05,1h-2.02c0.04,-0.33 0.07,-0.66 0.07,-1c0,-0.69 -0.1,-1.36 -0.26,-2h-3.38c0.08,0.66 0.14,1.32 0.14,2c0,0.34 -0.01,0.67 -0.04,1h-2.01c0.03,-0.33 0.05,-0.66 0.05,-1c0,-0.68 -0.07,-1.35 -0.16,-2H9.66c-0.09,0.65 -0.16,1.32 -0.16,2s0.07,1.34 0.16,2H13v2h-2.91c0.43,1.43 1.08,2.76 1.91,3.96V20h1v1.95C12.67,21.98 12.33,22 11.99,22C6.47,22 2,17.52 2,12zM15.97,8h2.95c-0.96,-1.65 -2.49,-2.93 -4.33,-3.56C15.19,5.55 15.65,6.75 15.97,8zM13.91,8C13.48,6.57 12.83,5.24 12,4.04c-0.83,1.2 -1.48,2.53 -1.91,3.96H13.91zM4,12c0,0.69 0.1,1.36 0.26,2h3.38c-0.08,-0.66 -0.14,-1.32 -0.14,-2s0.06,-1.34 0.14,-2H4.26C4.1,10.64 4,11.31 4,12zM8.03,16H5.08c0.96,1.66 2.49,2.93 4.33,3.56C8.81,18.45 8.35,17.25 8.03,16zM5.08,8h2.95c0.32,-1.25 0.78,-2.45 1.38,-3.56C7.57,5.07 6.04,6.34 5.08,8z"
+ android:fillAlpha="0.3"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
index 5aa0533..03589d3 100644
--- a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
+++ b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
@@ -168,6 +168,7 @@
</LinearLayout>
</LinearLayout>
<LinearLayout
+ android:id="@+id/content_background"
android:background="@drawable/people_space_content_background"
android:layout_gravity="center"
android:layout_width="match_parent"
@@ -187,7 +188,8 @@
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:visibility="gone"/>
+ android:visibility="gone"
+ android:scaleType="centerCrop"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
index 8dcddc2..7880cbd 100644
--- a/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
+++ b/packages/SystemUI/res/layout/screen_pinning_request_text_area.xml
@@ -16,65 +16,72 @@
* limitations under the License.
*/
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/screen_pinning_text_area"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="?android:attr/colorAccent"
- android:gravity="center_vertical">
+ android:fillViewport="true">
- <TextView
- android:id="@+id/screen_pinning_title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingEnd="48dp"
- android:paddingStart="48dp"
- android:paddingTop="43dp"
- android:text="@string/screen_pinning_title"
- android:textColor="@android:color/white"
- android:textSize="24sp" />
-
- <TextView
- android:id="@+id/screen_pinning_description"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/screen_pinning_title"
- android:paddingEnd="48dp"
- android:paddingStart="48dp"
- android:paddingTop="12.6dp"
- android:text="@string/screen_pinning_description"
- android:textColor="@android:color/white"
- android:textSize="16sp" />
-
- <Button
- android:id="@+id/screen_pinning_ok_button"
- style="@android:style/Widget.Material.Button"
+ <RelativeLayout
+ android:id="@+id/screen_pinning_text_area"
android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_alignParentEnd="true"
- android:layout_below="@+id/screen_pinning_description"
- android:layout_marginEnd="40dp"
- android:layout_marginTop="18dp"
- android:background="@null"
- android:paddingEnd="8dp"
- android:paddingStart="8dp"
- android:text="@string/screen_pinning_positive"
- android:textColor="@android:color/white"
- android:textSize="14sp" />
+ android:layout_height="wrap_content"
+ android:background="?android:attr/colorAccent"
+ android:gravity="center_vertical">
- <Button
- android:id="@+id/screen_pinning_cancel_button"
- style="@android:style/Widget.Material.Button"
- android:layout_width="wrap_content"
- android:layout_height="36dp"
- android:layout_alignTop="@id/screen_pinning_ok_button"
- android:layout_marginEnd="4dp"
- android:layout_toStartOf="@id/screen_pinning_ok_button"
- android:background="@null"
- android:paddingEnd="8dp"
- android:paddingStart="8dp"
- android:text="@string/screen_pinning_negative"
- android:textColor="@android:color/white"
- android:textSize="14sp" />
+ <TextView
+ android:id="@+id/screen_pinning_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingEnd="48dp"
+ android:paddingStart="48dp"
+ android:paddingTop="43dp"
+ android:text="@string/screen_pinning_title"
+ android:textColor="@android:color/white"
+ android:textSize="24sp" />
-</RelativeLayout>
+ <TextView
+ android:id="@+id/screen_pinning_description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/screen_pinning_title"
+ android:paddingEnd="48dp"
+ android:paddingStart="48dp"
+ android:paddingTop="12.6dp"
+ android:text="@string/screen_pinning_description"
+ android:textColor="@android:color/white"
+ android:textSize="16sp" />
+
+ <Button
+ android:id="@+id/screen_pinning_ok_button"
+ style="@android:style/Widget.Material.Button"
+ android:layout_width="wrap_content"
+ android:layout_height="36dp"
+ android:layout_alignParentEnd="true"
+ android:layout_below="@+id/screen_pinning_description"
+ android:layout_marginEnd="40dp"
+ android:layout_marginTop="18dp"
+ android:background="@null"
+ android:paddingEnd="8dp"
+ android:paddingStart="8dp"
+ android:text="@string/screen_pinning_positive"
+ android:textColor="@android:color/white"
+ android:textSize="14sp" />
+
+ <Button
+ android:id="@+id/screen_pinning_cancel_button"
+ style="@android:style/Widget.Material.Button"
+ android:layout_width="wrap_content"
+ android:layout_height="36dp"
+ android:layout_alignTop="@id/screen_pinning_ok_button"
+ android:layout_marginEnd="4dp"
+ android:layout_toStartOf="@id/screen_pinning_ok_button"
+ android:background="@null"
+ android:paddingEnd="8dp"
+ android:paddingStart="8dp"
+ android:text="@string/screen_pinning_negative"
+ android:textColor="@android:color/white"
+ android:textSize="14sp" />
+
+ </RelativeLayout>
+
+</ScrollView>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 0beb286..ba39d1e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Invoermetode"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ligging"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Ligging af"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Mediatoestel"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Net noodoproepe"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nuwe gebruiker"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nie gekoppel nie"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Geen netwerk nie"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi af"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index f56e84a..a193bbb 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"የግቤት ስልት"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"አካባቢ"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"አካባቢ ጠፍቷል"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"የሚዲያ መሣሪያ"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"የአደጋ ጊዜ ጥሪዎች ብቻ"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"አዲስ ተጠቃሚ"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"በይነመረብ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"አልተገናኘም"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ምንም አውታረ መረብ የለም"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ጠፍቷል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index aaaf778..a634281dc 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -348,6 +348,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"أسلوب الإدخال"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"الموقع الجغرافي"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"الموقع قيد الإيقاف"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"جهاز الوسائط"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"مكالمات طوارئ فقط"</string>
@@ -358,6 +362,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"مستخدم جديد"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"الإنترنت"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ليست متصلة"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"لا تتوفر شبكة"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"إيقاف Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 7e3e3cb..1151644 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ইনপুট পদ্ধতি"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"অৱস্থান"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"অৱস্থান অফ"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"মিডিয়া ডিভাইচ"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"জৰুৰীকালীন কল মাত্ৰ"</string>
@@ -353,7 +357,12 @@
<string name="quick_settings_user_title" msgid="8673045967216204537">"ব্যৱহাৰকাৰী"</string>
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"নতুন ব্যৱহাৰকাৰী"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ৱাই-ফাই"</string>
- <!-- no translation found for quick_settings_internet_label (6603068555872455463) -->
+ <string name="quick_settings_internet_label" msgid="6603068555872455463">"ইণ্টাৰনেট"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
<skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"সংযোগ হৈ থকা নাই"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"নেটৱৰ্ক নাই"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 6c22cc3..146add2f 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Daxiletmə metodu"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Yer"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Yer Deaktiv"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media cihazı"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Yalnız təcili zənglər"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Yeni istifadəçi"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"İnternet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Bağlantı yoxdur"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Şəbəkə yoxdur"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi sönülüdür"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2f3d6d2..77b101c 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -345,6 +345,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Metod unosa"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Lokacija je isključena"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medijski uređaj"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Samo hitni pozivi"</string>
@@ -355,6 +359,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novi korisnik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Veza nije uspostavljena"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nema mreže"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WiFi je isključen"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 925e86a..5977d04 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Метад уводу"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Месцазнаходжанне"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Вызначэнне месцазнаходжання адключана"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Мультымедыйная прылада"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Толькі экстранныя выклікі"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Новы карыстальнік"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Інтэрнэт"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Няма падключэння"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Няма сеткi"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi адключаны"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6a683c7..53eeac8 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Метод на въвеждане"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Местоположение"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Местоположението е изключено"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Мултимедийно устройство"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"Индикатор за силата на получения сигнал (RSSI)"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Само спешни обаждания"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Нов потребител"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Няма връзка"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Няма мрежа"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi е изключен"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 953ec00..b944dde 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ইনপুট পদ্ধতি"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"লোকেশন"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"লোকেশন বন্ধ করা আছে"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"মিডিয়া ডিভাইস"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"শুধুমাত্র জরুরি কল"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"নতুন ব্যবহারকারী"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ওয়াই-ফাই"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ইন্টারনেট"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"বিমানের জন্য নিরাপদ"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"নেটওয়ার্ক উপলভ্য"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"নেটওয়ার্ক উপলভ্য নেই"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"সংযুক্ত নয়"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"কোনো নেটওয়ার্ক নেই"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ওয়াই-ফাই বন্ধ"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 6bf1852..7717c65 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -345,6 +345,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Način unosa"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Utvrđivanje lokacije isključeno"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medijski uređaj"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Samo pozivi za hitne slučajeve"</string>
@@ -355,6 +359,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novi korisnik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Sigurno za rad u zrakoplovu"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Mreže su dostupne"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Mreže nisu dostupne"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nije povezano"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nema mreže"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WiFi je isključen"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 71105cc..f648bc6 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Mètode d\'introducció"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ubicació"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Ubicació desactivada"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositiu multimèdia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Només trucades d\'emergència"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Usuari nou"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Desconnectat"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No hi ha cap xarxa"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desconnectada"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 65e6767..4d14d2b 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Metoda zadávání dat"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Poloha"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Poloha vypnuta"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Mediální zařízení"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Pouze tísňová volání"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nový uživatel"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nepřipojeno"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Žádná síť"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi vypnuta"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index e50aa57..95b1a55 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Inputmetode"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Placering"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Placering fra"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medieenhed"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Kun nødopkald"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Ny bruger"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ikke forbundet"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Intet netværk"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi slået fra"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 3cdebf9..e6acd87 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Eingabemethode"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Standort"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Standort aus"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Mediengerät"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Nur Notrufe"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Neuer Nutzer"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WLAN"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nicht verbunden"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Kein Netz"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WLAN aus"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index c6ae7f4..867c7d2 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Μέθοδος εισαγωγής"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Τοποθεσία"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Τοποθεσία απενεργοποιημένη"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Συσκευή μέσων"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Μόνο κλήσεις έκτακτης ανάγκης"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Νέος χρήστης"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Διαδίκτυο"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Ασφαλές για πτήση"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Υπάρχουν διαθέσιμα δίκτυα"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Δεν υπάρχουν διαθέσιμα δίκτυα"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Μη συνδεδεμένο"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Κανένα δίκτυο"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ανενεργό"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index ea25ec6..185af57 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Input Method"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Location Off"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media device"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Emergency Calls Only"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index a373a5c..3517f87 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Input Method"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Location Off"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media device"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Emergency Calls Only"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index ea25ec6..185af57 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Input Method"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Location Off"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media device"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Emergency Calls Only"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index ea25ec6..185af57 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Input Method"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Location Off"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media device"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Emergency Calls Only"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 101d112..306116c 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Input Method"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Location"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Location Off"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media device"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Emergency Calls Only"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"New user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Airplane-safe"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Networks available"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Networks unavailable"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Off"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 1fc1609..27c424b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Método de introducción"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ubicación"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Ubicación desactivada"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo multimedia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Solo emergencia"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Usuario nuevo"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Sin conexión"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Sin red"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desactivada"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index dd36a64..ab5d0d2 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Método de entrada"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Ubicación"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Ubicación desactivada"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo multimedia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Solo llamadas de emergencia"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nuevo usuario"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"No conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"No hay red."</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desactivado"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index fb27be9..6c7e19a 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Sisestusmeetod"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Asukoht"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Asukoht on väljas"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Meediaseade"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Ainult hädaabikõned"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Uus kasutaja"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ühendus puudub"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Võrku pole"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WiFi-ühendus on väljas"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index d8b21c6..da7733c 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Idazketa-metodoa"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Kokapena"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Kokapena desaktibatuta"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Multimedia-gailua"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Larrialdi-deiak soilik"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Erabiltzaile berria"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wifia"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Konektatu gabe"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ez dago sarerik"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi konexioa desaktibatuta"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index df306f8..2bc2e57 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"روش ورودی"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"مکان"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"مکان خاموش"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"دستگاه رسانه"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"فقط تماسهای اضطراری"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"کاربر جدید"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"اینترنت"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"ایمن در هواپیما"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"شبکه دردسترس است"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"شبکه دردسترس نیست"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"متصل نیست"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"شبکهای موجود نیست"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi خاموش است"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4e0af37..28708b9 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Syöttötapa"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Sijainti"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Sijainti ei käytössä"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medialaite"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Vain hätäpuhelut"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Uusi käyttäjä"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ei yhteyttä"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ei verkkoa"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi-yhteys pois käytöstä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 8c944a4..8235638 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Mode de saisie"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Position"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Localisation désactivée"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Appareil multimédia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Appels d\'urgence uniquement"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nouvel utilisateur"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Sécuritaire pour les avions"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Réseaux accessibles"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Aucun réseau accessible"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Non connecté"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Aucun réseau"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi désactivé"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7ad239d..50a3cfb 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Mode de saisie"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localisation"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Localisation désactivée"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Appareil multimédia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Appels d\'urgence"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nouvel utilisateur"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Non connecté"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Aucun réseau"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi désactivé"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 145b3c0..4c6a53e 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Método de introdución de texto"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localización"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Localización desactivada"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo multimedia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Só chamadas de emerxencia"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novo usuario"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wifi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Non conectada"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Non hai rede"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wifi desactivada"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index ea7af17..add1ef5 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ઇનપુટ પદ્ધતિ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"સ્થાન"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"સ્થાન બંધ"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"મીડિયા ઉપકરણ"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ફક્ત ઇમર્જન્સી કૉલ"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"નવો વપરાશકર્તા"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"વાઇ-ફાઇ"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ઇન્ટરનેટ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"કનેક્ટ થયેલ નથી"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"કોઈ નેટવર્ક નથી"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"વાઇ-ફાઇ બંધ"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a8bed5b..b4d61bb 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"इनपुट विधि"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"जगह"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"जगह की जानकारी बंद है"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"मीडिया डिवाइस"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"सिर्फ़ आपातकालीन कॉल"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"नया उपयोगकर्ता"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"वाई-फ़ाई"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"इंटरनेट"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"कनेक्ट नहीं है"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"कोई नेटवर्क नहीं"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"वाई-फ़ाई बंद"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 4ffa5b2..e5cf20a 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -345,6 +345,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Način unosa"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Lokacija je isključena"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medijski uređaj"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Samo hitni pozivi"</string>
@@ -355,6 +359,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novi korisnik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Sigurno za rad u zrakoplovu"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Mreže su dostupne"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Mreže nisu dostupne"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nije povezano"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nema mreže"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi isključen"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index cff5b0d..958e25f6 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Beviteli módszer"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Tartózkodási hely"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Hely kikapcsolva"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Médiaeszköz"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Csak segélyhívások"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Új felhasználó"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nincs kapcsolat"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nincs hálózat"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi kikapcsolva"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 91ffe73..4fd1abe 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Մուտքագրման եղանակը"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Տեղորոշում"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Անջատել տեղադրությունը"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Մեդիա սարք"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Միայն շտապ կանչեր"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Նոր օգտատեր"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Ինտերնետ"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Ցանցեր, որոնք անվտանգ են ինքնաթիռում"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Հասանելի ցանցեր"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Անհասանելի ցանցեր"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Միացված չէ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ցանց չկա"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi-ը անջատված է"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f9e7397..4136ead 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Metode Masukan"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokasi"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Lokasi Nonaktif"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Perangkat media"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Panggilan Darurat Saja"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Pengguna baru"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Tidak Terhubung"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Tidak Ada Jaringan"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Mati"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index db5dac43..15c07e4 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Innsláttaraðferð"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Staðsetning"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Staðsetning óvirk"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Margmiðlunartæki"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Aðeins neyðarsímtöl"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nýr notandi"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Engin tenging"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ekkert net"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Slökkt á Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 86e65bb..299824b 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Metodo di immissione"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Geolocalizzazione"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Geolocalizz. non attiva"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo multimediale"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Solo chiamate di emergenza"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nuovo utente"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Non connessa"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nessuna rete"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi disattivato"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 8548dae..e8cc8bf 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"שיטת קלט"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"מיקום"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"מיקום כבוי"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"מכשיר מדיה"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"שיחות חירום בלבד"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"משתמש חדש"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"אינטרנט"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"אין חיבור"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"אין רשת"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi כבוי"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 6cd5608..459b520 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"入力方法"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"位置情報"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"現在地OFF"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"メディアデバイス"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"緊急通報のみ"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"新しいユーザー"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"インターネット"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"接続されていません"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ネットワークなし"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi OFF"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 52d9f0e..20f2d03 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"შეყვანის მეთოდი"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"მდებარეობა"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"მდებარეობა გამორთულია"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"მედია მოწყობილობა"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"მხოლოდ გადაუდებელი დახმარების ზარებისთვის"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ახალი მომხმარებელი"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ინტერნეტი"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"თვითმფრინავისთვის უსაფრთხო"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"ქსელები ხელმისაწვდომია"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"ქსელები მიუწვდომელია"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"არ არის დაკავშირებული."</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ქსელი არ არის"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi გამორთულია"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index fcf8743..65f3032 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Енгізу әдісі"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Орналасу"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Орын өшірулі"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Meдиа құрылғысы"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI (алынған сигнал қуатының көрсеткіші)"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Құтқару қызметіне ғана қоңырау шалынады"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Жаңа пайдаланушы"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Жалғанбаған"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Желі жоқ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi өшірулі"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index e92bf9b..a4f6e0a 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"វិធីសាស្ត្របញ្ចូល"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ទីតាំង"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"ទីតាំងបានបិទ"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"ឧបករណ៍មេឌៀ"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ការហៅទៅលេខសង្គ្រោះបន្ទាន់តែប៉ុណ្ណោះ"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"អ្នកប្រើថ្មី"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"អ៊ីនធឺណិត"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"មិនបានតភ្ជាប់"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"គ្មានបណ្ដាញ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"វ៉ាយហ្វាយបានបិទ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index d7a0adc..e02ed5a 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ಇನ್ಪುಟ್ ವಿಧಾನ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ಸ್ಥಳ"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"ಸ್ಥಳ ಆಫ್ ಆಗಿದೆ"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"ಮಾಧ್ಯಮ ಸಾಧನ"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ತುರ್ತು ಕರೆಗಳು ಮಾತ್ರ"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ಹೊಸ ಬಳಕೆದಾರರು"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ವೈ-ಫೈ"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ಇಂಟರ್ನೆಟ್"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ಸಂಪರ್ಕಗೊಂಡಿಲ್ಲ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ನೆಟ್ವರ್ಕ್ ಇಲ್ಲ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ವೈ-ಫೈ ಆಫ್"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 54bcfb9..e9d33fa 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"입력 방법"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"위치"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"위치 사용 중지"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"미디어 기기"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"긴급 통화만 허용"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"신규 사용자"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"인터넷"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"연결되어 있지 않음"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"네트워크가 연결되지 않음"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi 꺼짐"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index d513380..f4191d4 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Киргизүү ыкмасы"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Жайгашкан жер"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Жайгашытрууну өчүрүү"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Медиа түзмөгү"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Кырсыктаганда гана чалуу"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Жаңы колдонуучу"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Байланышкан жок"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Желе жок"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi өчүк"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 7e595cd..0f0236f 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ວິທີການປ້ອນຂໍ້ມູນ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ສະຖານທີ່"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"ຂໍ້ມູນສະຖານທີ່ປິດຢູ່"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"ອຸປະກອນສື່"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ໂທສຸກເສີນເທົ່ານັ້ນ"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ຜູ່ໃຊ້ໃໝ່"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ອິນເຕີເນັດ"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"ປອດໄພກັບໃນຍົນ"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"ມີເຄືອຂ່າຍທີ່ສາມາດໃຊ້ໄດ້"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"ບໍ່ມີເຄືອຂ່າຍທີ່ສາມາດໃຊ້ໄດ້"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ບໍ່ໄດ້ເຊື່ອມຕໍ່"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ບໍ່ມີເຄືອຂ່າຍ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ປິດ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index e0c27a9..8d9051d 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Įvesties metodas"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Vietovė"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Vietovė išjungta"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medijos įrenginys"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Tik skambučiai pagalbos numeriu"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Naujas naudotojas"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internetas"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Neprisijungta"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Tinklo nėra"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"„Wi-Fi“ išjungta"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index ff36f51..1cde532 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -345,6 +345,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Ievades metode"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Atrašanās vieta"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Atrašanās vieta izslēgta"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Multivides ierīce"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Tikai ārkārtas izsaukumi"</string>
@@ -355,6 +359,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Jauns lietotājs"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internets"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nav izveidots savienojums"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nav tīkla"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ir izslēgts"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 203d8b9..a006bc9 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Метод на внес"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Локација"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Исклучи локација"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Медиумски уред"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Само итни повици"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Нов корисник"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Не е поврзано"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Нема мрежа"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi е исклучено"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 77925ae..4d2898f 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ടൈപ്പുചെയ്യൽ രീതി"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ലൊക്കേഷൻ"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"ലൊക്കേഷൻ ഓഫാണ്"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"മീഡിയ ഉപകരണം"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"അടിയന്തിര കോളുകൾ മാത്രം"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"പുതിയ ഉപയോക്താവ്"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"വൈഫൈ"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ഇന്റർനെറ്റ്"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"കണക്റ്റ് ചെയ്തിട്ടില്ല"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"നെറ്റ്വർക്ക് ഒന്നുമില്ല"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"വൈഫൈ ഓഫുചെയ്യുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index c772294..8845b07 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Оруулах арга"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Байршил"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Байршил идэвхгүй"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Медиа төхөөрөмж"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Зөвхөн яаралтай дуудлага"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Шинэ хэрэглэгч"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернэт"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Холбогдоогүй"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Сүлжээгүй"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi унтарсан"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 965b895..48498b7 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"इनपुट पद्धत"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"स्थान"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"स्थान बंद"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"मीडिया डिव्हाइस"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"फक्त आणीबाणीचे कॉल"</string>
@@ -353,7 +357,12 @@
<string name="quick_settings_user_title" msgid="8673045967216204537">"वापरकर्ता"</string>
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"नवीन वापरकर्ता"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"वाय-फाय"</string>
- <!-- no translation found for quick_settings_internet_label (6603068555872455463) -->
+ <string name="quick_settings_internet_label" msgid="6603068555872455463">"इंटरनेट"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
<skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"कनेक्ट केले नाही"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"नेटवर्क नाही"</string>
@@ -456,11 +465,9 @@
<string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"प्रोफाईल दर्शवा"</string>
<string name="user_add_user" msgid="4336657383006913022">"वापरकर्ता जोडा"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"नवीन वापरकर्ता"</string>
- <!-- no translation found for guest_exit_guest_dialog_title (2034481024623462357) -->
- <skip />
+ <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"अतिथी सत्र संपायचे का?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"या सत्रातील सर्व अॅप्स आणि डेटा हटवला जाईल."</string>
- <!-- no translation found for guest_exit_guest_dialog_remove (8533184512885775423) -->
- <skip />
+ <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"सत्र संपवा"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"अतिथी, तुमचे पुन्हा स्वागत आहे!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"तुम्ही तुमचे सत्र सुरू ठेवू इच्छिता?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"येथून सुरू करा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index d3e3601..4204417 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Kaedah Input"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokasi"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Lokasi Dimatikan"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Peranti media"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Panggilan Kecemasan Sahaja"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Pengguna baharu"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Tidak Disambungkan"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Tiada Rangkaian"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Dimatikan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 0c1f9cb..9b7488e 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ထည့်သွင်းရန်နည်းလမ်း"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"တည်နေရာ"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"တည်နေရာပြမှု မရှိ"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"မီဒီယာ စက်ပစ္စည်း"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"အရေးပေါ်ခေါ်ဆိုမှုများသာ"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"အသုံးပြုသူ အသစ်"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"အင်တာနက်"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ချိတ်ဆက်မထားပါ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ကွန်ရက်မရှိပါ"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ဝိုင်ဖိုင်ပိတ်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 565e7fe..490ba99 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Inndatametode"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Sted"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Posisjon av"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medieenhet"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Bare nødanrop"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Ny bruker"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internett"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ikke tilkoblet"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ingen nettverk"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi er av"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 9d95cf0..cf267fd 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"आगत विधि"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"स्थान"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"स्थान बन्द छ"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"मिडिया उपकरण"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"आपत्कालीन कल मात्र"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"नयाँ प्रयोगकर्ता"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"इन्टरनेट"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"जोडिएको छैन"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"नेटवर्क छैन"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi बन्द"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index d0aef6f..672d2f6 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -77,6 +77,9 @@
<color name="biometric_dialog_accent">#ff80cbc4</color> <!-- light teal -->
<color name="biometric_dialog_error">#fff28b82</color> <!-- red 300 -->
+ <!-- UDFPS colors -->
+ <color name="udfps_enroll_icon">#ffffff</color> <!-- 100% white -->
+
<color name="GM2_green_500">#FF41Af6A</color>
<color name="GM2_blue_500">#5195EA</color>
<color name="GM2_red_500">#E25142</color>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index f598fa3..ddb9abc 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Invoermethode"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Locatie"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Locatie uit"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media-apparaat"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Alleen noodoproepen"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nieuwe gebruiker"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wifi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Niet verbonden"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Geen netwerk"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wifi uit"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 1e07dd4..ce6723e 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ଇନପୁଟ୍ ପଦ୍ଧତି"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ଲୋକେସନ୍"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"ଲୋକେସନ୍ ଅଫ୍"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"ମିଡିଆ ଡିଭାଇସ୍"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"କେବଳ ଜରୁରୀକାଳୀନ କଲ୍"</string>
@@ -353,7 +357,12 @@
<string name="quick_settings_user_title" msgid="8673045967216204537">"ୟୁଜର୍"</string>
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ୱାଇ-ଫାଇ"</string>
- <!-- no translation found for quick_settings_internet_label (6603068555872455463) -->
+ <string name="quick_settings_internet_label" msgid="6603068555872455463">"ଇଣ୍ଟରନେଟ୍"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
<skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ସଂଯୁକ୍ତ ହୋଇନାହିଁ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ନେଟ୍ୱର୍କ ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 7d5bc96..ad40d6c 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ਇਨਪੁੱਟ ਵਿਧੀ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ਟਿਕਾਣਾ"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਬੰਦ"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"ਮੀਡੀਆ ਡੀਵਾਈਸ"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ਸਿਰਫ਼ ਸੰਕਟਕਾਲੀਨ ਕਾਲਾਂ"</string>
@@ -353,7 +357,12 @@
<string name="quick_settings_user_title" msgid="8673045967216204537">"ਵਰਤੋਂਕਾਰ"</string>
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"ਵਾਈ-ਫਾਈ"</string>
- <!-- no translation found for quick_settings_internet_label (6603068555872455463) -->
+ <string name="quick_settings_internet_label" msgid="6603068555872455463">"ਇੰਟਰਨੈੱਟ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
<skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ਕੋਈ ਨੈੱਟਵਰਕ ਨਹੀਂ"</string>
@@ -456,11 +465,9 @@
<string name="accessibility_multi_user_switch_quick_contact" msgid="4504508915324898576">"ਪ੍ਰੋਫਾਈਲ ਦਿਖਾਓ"</string>
<string name="user_add_user" msgid="4336657383006913022">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="user_new_user_name" msgid="2019166282704195789">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>
- <!-- no translation found for guest_exit_guest_dialog_title (2034481024623462357) -->
- <skip />
+ <string name="guest_exit_guest_dialog_title" msgid="2034481024623462357">"ਕੀ ਮਹਿਮਾਨ ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰਨਾ ਹੈ?"</string>
<string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"ਇਸ ਸੈਸ਼ਨ ਵਿੱਚ ਸਾਰੀਆਂ ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਨੂੰ ਮਿਟਾ ਦਿੱਤਾ ਜਾਏਗਾ।"</string>
- <!-- no translation found for guest_exit_guest_dialog_remove (8533184512885775423) -->
- <skip />
+ <string name="guest_exit_guest_dialog_remove" msgid="8533184512885775423">"ਸੈਸ਼ਨ ਸਮਾਪਤ ਕਰੋ"</string>
<string name="guest_wipe_session_title" msgid="7147965814683990944">"ਮਹਿਮਾਨ, ਫਿਰ ਤੁਹਾਡਾ ਸੁਆਗਤ ਹੈ!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"ਕੀ ਤੁਸੀਂ ਆਪਣਾ ਸੈਸ਼ਨ ਜਾਰੀ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"ਸ਼ੁਰੂ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 561e70d..75abfda 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Metoda wprowadzania"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokalizacja"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Lokalizacja wyłączona"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Urządzenie multimedialne"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Tylko połączenia alarmowe"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nowy użytkownik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Brak połączenia"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Brak sieci"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi wyłączone"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 7fe53d3..1ab1002 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Método de entrada"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localização"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Localização desativada"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo de mídia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Chamadas de emergência"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novo usuário"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Segura para aviões"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Redes disponíveis"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Redes indisponíveis"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Não conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Sem rede"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desligado"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index dd154e8..06b67fb 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Método de Introdução"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localização"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Localização Desativada"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo multimédia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Apenas chamadas de emergência"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novo utilizador"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Seguras para aviões"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Redes disponíveis"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Redes indisponíveis"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Não Ligado"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Sem Rede"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Desligado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 7fe53d3..1ab1002 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Método de entrada"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Localização"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Localização desativada"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispositivo de mídia"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Chamadas de emergência"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Novo usuário"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Segura para aviões"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Redes disponíveis"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Redes indisponíveis"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Não conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Sem rede"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi desligado"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 317fc09..54d53af 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -345,6 +345,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Metodă de introducere"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Locație"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Localizarea este dezactivată"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Dispozitiv media"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Numai apeluri de urgență"</string>
@@ -355,6 +359,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Utilizator nou"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Neconectată"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nicio rețea"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi deconectat"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index bbb014e..b6c2812 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Способ ввода"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Геолокация"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Местоположение выкл."</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Режим медиа"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Экстр. вызов"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Новый пользователь"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Нет соединения"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Нет сети"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi выкл."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index a7a2bb7..c1ba12b 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ආදාන ක්රමය"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ස්ථානය"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"ස්ථානය අක්රියයි"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"මාධ්ය උපාංගය"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"හදිසි ඇමතුම් පමණි"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"නව පරිශීලකයා"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"අන්තර්ජාලය"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"සම්බන්ධ වී නොමැත"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ජාලයක් නැත"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi අක්රියයි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 7eb5297..dfa371b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Metóda vstupu"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Poloha"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Poloha vypnutá"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Mediálne zariadenie"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Len tiesňové volania"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nový používateľ"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi‑Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nepripojené"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Žiadna sieť"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Sieť Wi‑Fi je vypnutá"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 6d23f26..5f5ee65 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Način vnosa"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokacija"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Lokacija izklopljena"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Predstavnostna naprava"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Le klici v sili"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Nov uporabnik"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Povezava ni vzpostavljena"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ni omrežja"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi izklopljen"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 7e89b93..e1ca274 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Metoda e hyrjes"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Vendndodhja"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Vendndodhja është e çaktivizuar"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Pajisje e jashtme ruajtëse"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Vetëm telefonata urgjence"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Përdorues i ri"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Nuk është i lidhur"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Nuk ka rrjet"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi është i çaktivizuar"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index af5175c..d7bc5a1 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -345,6 +345,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Метод уноса"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Локација"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Локација је искључена"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Медијски уређај"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Само хитни позиви"</string>
@@ -355,6 +359,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Нови корисник"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WiFi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Интернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Веза није успостављена"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Нема мреже"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WiFi је искључен"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 41bca7c..3e38bdd 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Inmatningsmetod"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Plats"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Plats har inaktiverats"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medieenhet"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Endast nödsamtal"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Ny användare"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ej ansluten"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Inget nätverk"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi av"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index f122013..5d1698d 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Mbinu ya uingizaji"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Kutambua Mahali"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Kitambua eneo kimezimwa"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Kifaa cha faili"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Simu za Dharura Pekee"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Mtumiaji mpya"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Intaneti"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Hali salama ya ndegeni"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Mitandao inapatikana"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Mitandao haipatikani"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Haijaunganishwa"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Hakuna Mtandao"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi Imezimwa"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index c076a03..ebb7fa6 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"உள்ளீட்டு முறை"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"இருப்பிடம்"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"இருப்பிடத்தை முடக்கு"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"மீடியா சாதனம்"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"அவசரகால அழைப்புகள் மட்டும்"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"புதியவர்"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"வைஃபை"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"இணையம்"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"இணைக்கப்படவில்லை"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"நெட்வொர்க் இல்லை"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"வைஃபையை முடக்கு"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index fca5107..1456a8c 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ఇన్పుట్ పద్ధతి"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"లొకేషన్"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"లొకేషన్ ఆఫ్లో ఉంది"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"ప్రసార మాధ్యమ పరికరం"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"ఎమర్జెన్సీ కాల్స్ మాత్రమే"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"కొత్త వినియోగదారు"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"ఇంటర్నెట్"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"కనెక్ట్ చేయబడలేదు"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"నెట్వర్క్ లేదు"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi ఆఫ్లో ఉంది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index c909d37..65ee106 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"วิธีป้อนข้อมูล"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"ตำแหน่ง"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"ปิดตำแหน่ง"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"อุปกรณ์สื่อ"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"โทรฉุกเฉินเท่านั้น"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"ผู้ใช้ใหม่"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"อินเทอร์เน็ต"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"ไม่ได้เชื่อมต่อ"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"ไม่มีเครือข่าย"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"ปิด WiFi"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 2e75fa3..9eab088 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Pamamaraan ng Pag-input"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Lokasyon"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Naka-off ang Lokasyon"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Device ng media"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Mga Pang-emergency na Tawag Lamang"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Bagong user"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Hindi Nakakonekta"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Walang Network"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Naka-off ang Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 98552b1..921cce8 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Giriş Yöntemi"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Konum"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Konum Bilgisi Kapalı"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Medya cihazı"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Yalnızca Acil Çağrılar İçin"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Yeni kullanıcı"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Kablosuz"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"İnternet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Bağlı Değil"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ağ yok"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Kablosuz Kapalı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index b70d36a..66a8cfb 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -346,6 +346,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Метод введення"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Місцезнаходження"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Місцезнаходження вимкнено"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Носій"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Екстрені виклики"</string>
@@ -356,6 +360,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Новий користувач"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Інтернет"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Не під’єднано."</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Немає мережі"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi вимкнено"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index bbadf6a..3865bc0 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"ان پٹ کا طریقہ"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"مقام"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"مقام آف"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"میڈیا آلہ"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"صرف ہنگامی کالیں"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"نیا صارف"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"انٹرنیٹ"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"مربوط نہیں ہے"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"کوئی نیٹ ورک نہیں ہے"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi آف ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index a20676d..d6061a6 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Kiritish usuli"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Joylashuv"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Joylashuvni aniqlash xizmati yoqilmagan"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Media qurilma"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Favqulodda chaqiruvlar"</string>
@@ -354,6 +358,9 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Yangi foydalanuvchi"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <string name="quick_settings_airplane_safe_label" msgid="2665758539772645899">"Samolyot uchun xavfsiz"</string>
+ <string name="quick_settings_networks_available" msgid="1875138606855420438">"Tarmoqlar mavjud"</string>
+ <string name="quick_settings_networks_unavailable" msgid="1167847013337940082">"Tarmoqqa ulanish imkonsiz"</string>
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Ulanmagan"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Tarmoq mavjud emas"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi o‘chiq"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 5de7df6a..23e72c1 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Phương thức nhập"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Vị trí"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Tắt vị trí"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Thiết bị phương tiện"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Chỉ cuộc gọi khẩn cấp"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Người dùng mới"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"Internet"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Chưa được kết nối"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Không có mạng nào"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Tắt Wi-Fi"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7f3f394..55b524e 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -63,9 +63,9 @@
<string name="usb_debugging_allow" msgid="1722643858015321328">"允许"</string>
<string name="usb_debugging_secondary_user_title" msgid="7843050591380107998">"不允许使用 USB 调试功能"</string>
<string name="usb_debugging_secondary_user_message" msgid="3740347841470403244">"目前已登录此设备的用户无法开启 USB 调试功能。要使用此功能,请切换为主要用户的帐号。"</string>
- <string name="wifi_debugging_title" msgid="7300007687492186076">"要允许在此网络上进行无线调试吗?"</string>
+ <string name="wifi_debugging_title" msgid="7300007687492186076">"要允许通过此网络上进行无线调试吗?"</string>
<string name="wifi_debugging_message" msgid="5461204211731802995">"网络名称 (SSID)\n<xliff:g id="SSID_0">%1$s</xliff:g>\n\nWLAN 地址 (BSSID)\n<xliff:g id="BSSID_1">%2$s</xliff:g>"</string>
- <string name="wifi_debugging_always" msgid="2968383799517975155">"在此网络上始终允许"</string>
+ <string name="wifi_debugging_always" msgid="2968383799517975155">"始终允许通过此网络进行调试"</string>
<string name="wifi_debugging_allow" msgid="4573224609684957886">"允许"</string>
<string name="wifi_debugging_secondary_user_title" msgid="2493201475880517725">"不允许使用无线调试功能"</string>
<string name="wifi_debugging_secondary_user_message" msgid="4492383073970079751">"目前已登录此设备的用户无法开启无线调试功能。要使用此功能,请切换为主要用户的帐号。"</string>
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"输入法"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"位置信息"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"位置信息:关闭"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"媒体设备"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"只能拨打紧急呼救电话"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"新用户"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"WLAN"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"互联网"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"未连接"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"无网络"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"WLAN:关闭"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 485f1cf..701f32d 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"輸入法"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"位置"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"位置資訊已關閉"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"媒體裝置"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"只可撥打緊急電話"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"新使用者"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"互聯網"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"未連線"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"沒有網絡"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi 關閉"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 1edeacd..4210ec1 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"輸入法"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"定位"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"定位服務已關閉"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"媒體裝置"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"僅可撥打緊急電話"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"新使用者"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"網際網路"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"未連線"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"沒有網路"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"Wi-Fi 已關閉"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 58baebc..940fc19 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -344,6 +344,10 @@
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Indlela yokungenayo"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Indawo"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Indawo ivaliwe"</string>
+ <!-- no translation found for quick_settings_camera_label (1367149596242401934) -->
+ <skip />
+ <!-- no translation found for quick_settings_mic_label (8245831073612564953) -->
+ <skip />
<string name="quick_settings_media_device_label" msgid="8034019242363789941">"Idivayisi yemidiya"</string>
<string name="quick_settings_rssi_label" msgid="3397615415140356701">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="7499207215265078598">"Amakholi aphuthumayo kuphela"</string>
@@ -354,6 +358,12 @@
<string name="quick_settings_user_new_user" msgid="3347905871336069666">"Umsebenzisi omusha"</string>
<string name="quick_settings_wifi_label" msgid="2879507532983487244">"I-Wi-Fi"</string>
<string name="quick_settings_internet_label" msgid="6603068555872455463">"I-inthanethi"</string>
+ <!-- no translation found for quick_settings_airplane_safe_label (2665758539772645899) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_available (1875138606855420438) -->
+ <skip />
+ <!-- no translation found for quick_settings_networks_unavailable (1167847013337940082) -->
+ <skip />
<string name="quick_settings_wifi_not_connected" msgid="4071097522427039160">"Akuxhunyiwe"</string>
<string name="quick_settings_wifi_no_network" msgid="6003178398713839313">"Ayikho inethiwekhi"</string>
<string name="quick_settings_wifi_off_label" msgid="4003379736176547594">"I-Wi-Fi icimile"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9731d78..3f6b8ef 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -178,6 +178,9 @@
<color name="biometric_dialog_accent">#ff008577</color> <!-- dark teal -->
<color name="biometric_dialog_error">#ffd93025</color> <!-- red 600 -->
+ <!-- UDFPS colors -->
+ <color name="udfps_enroll_icon">#000000</color> <!-- 100% black -->
+
<!-- Logout button -->
<color name="logout_button_bg_color">#ccffffff</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 101124e..93d2f75 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -107,7 +107,7 @@
<!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
<string name="quick_settings_tiles_stock" translatable="false">
- wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness
+ wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness,cameratoggle,mictoggle
</string>
<!-- The tiles to display in QuickSettings -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 72dd724..ae55d95 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -619,7 +619,7 @@
<dimen name="z_distance_between_notifications">0.5dp</dimen>
<!-- The height of the divider between the individual notifications. -->
- <dimen name="notification_divider_height">4dp</dimen>
+ <dimen name="notification_divider_height">2dp</dimen>
<!-- The corner radius of the shadow behind the notification. -->
<dimen name="notification_shadow_radius">0dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 86af464..ac2e342 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -821,6 +821,10 @@
<string name="quick_settings_location_label">Location</string>
<!-- QuickSettings: Location (Off) [CHAR LIMIT=NONE] -->
<string name="quick_settings_location_off_label">Location Off</string>
+ <!-- QuickSettings: Camera [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_camera_label">Block Camera</string>
+ <!-- QuickSettings: Microphone [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_mic_label">Mute Microphone</string>
<!-- QuickSettings: Media device [CHAR LIMIT=NONE] -->
<string name="quick_settings_media_device_label">Media device</string>
<!-- QuickSettings: RSSI [CHAR LIMIT=NONE] -->
@@ -841,6 +845,12 @@
<string name="quick_settings_wifi_label">Wi-Fi</string>
<!-- QuickSettings: Internet [CHAR LIMIT=NONE] -->
<string name="quick_settings_internet_label">Internet</string>
+ <!-- QuickSettings: Airplane-safe [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_airplane_safe_label">Airplane-safe</string>
+ <!-- QuickSettings: networks available [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_networks_available">Networks available</string>
+ <!-- QuickSettings: networks unavailable [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_networks_unavailable">Networks unavailable</string>
<!-- QuickSettings: Wifi (Not connected) [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_not_connected">Not Connected</string>
<!-- QuickSettings: Wifi (No network) [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 6eec5dc..902de23 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -50,6 +50,10 @@
android:key="bluetooth"
android:title="@string/quick_settings_bluetooth_label" />
+ <com.android.systemui.tuner.StatusBarSwitch
+ android:key="cameratoggle"
+ android:title="@string/quick_settings_camera_label" />
+
<!-- nfc -->
<!-- tty -->
<!-- speakerphone -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index 4d1fb38..6d67f21 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -257,7 +257,7 @@
.setContentText("Restart SysUI for changes to take effect.");
Intent i = new Intent("com.android.systemui.action.RESTART").setData(
Uri.parse("package://" + pkg));
- PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0);
+ PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, PendingIntent.FLAG_MUTABLE_UNAUDITED);
nb.addAction(new Action.Builder(null, "Restart SysUI", pi).build());
mContext.getSystemService(NotificationManager.class)
.notify(SystemMessage.NOTE_PLUGIN, nb.build());
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ChoreographerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ChoreographerCompat.java
deleted file mode 100644
index 76b447e..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ChoreographerCompat.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.shared.system;
-
-import static android.view.Choreographer.CALLBACK_INPUT;
-
-import android.view.Choreographer;
-
-/**
- * Wraps the internal choreographer.
- */
-public class ChoreographerCompat {
-
- /**
- * Posts an input callback to the choreographer.
- */
- public static void postInputFrame(Choreographer choreographer, Runnable runnable) {
- choreographer.postCallback(CALLBACK_INPUT, runnable, null);
- }
-
- public static Choreographer getSfInstance() {
- return Choreographer.getSfInstance();
- }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
index 27cb4f6..19e7d7e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InteractionJankMonitorWrapper.java
@@ -49,16 +49,12 @@
public @interface CujType {
}
- public static void init(@NonNull View view) {
- InteractionJankMonitor.getInstance().init(view);
+ public static boolean begin(View v, @CujType int cujType) {
+ return InteractionJankMonitor.getInstance().begin(v, cujType);
}
- public static boolean begin(@CujType int cujType) {
- return InteractionJankMonitor.getInstance().begin(cujType);
- }
-
- public static boolean begin(@CujType int cujType, long timeout) {
- return InteractionJankMonitor.getInstance().begin(cujType, timeout);
+ public static boolean begin(View v, @CujType int cujType, long timeout) {
+ return InteractionJankMonitor.getInstance().begin(v, cujType, timeout);
}
public static boolean end(@CujType int cujType) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index bdfc65e..937c1df 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -90,6 +90,10 @@
public static final int SYSUI_STATE_GLOBAL_ACTIONS_SHOWING = 1 << 15;
// The one-handed mode is active
public static final int SYSUI_STATE_ONE_HANDED_ACTIVE = 1 << 16;
+ // Allow system gesture no matter the system bar(s) is visible or not
+ public static final int SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY = 1 << 17;
+ // The IME is showing
+ public static final int SYSUI_STATE_IME_SHOWING = 1 << 18;
@Retention(RetentionPolicy.SOURCE)
@IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -107,8 +111,10 @@
SYSUI_STATE_TRACING_ENABLED,
SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED,
SYSUI_STATE_BUBBLES_EXPANDED,
+ SYSUI_STATE_GLOBAL_ACTIONS_SHOWING,
SYSUI_STATE_ONE_HANDED_ACTIVE,
- SYSUI_STATE_GLOBAL_ACTIONS_SHOWING
+ SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
+ SYSUI_STATE_IME_SHOWING
})
public @interface SystemUiStateFlags {}
@@ -133,6 +139,9 @@
? "asst_gesture_constrain" : "");
str.add((flags & SYSUI_STATE_BUBBLES_EXPANDED) != 0 ? "bubbles_expanded" : "");
str.add((flags & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0 ? "one_handed_active" : "");
+ str.add((flags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0
+ ? "allow_gesture" : "");
+ str.add((flags & SYSUI_STATE_IME_SHOWING) != 0 ? "ime_visible" : "");
return str.toString();
}
@@ -175,6 +184,9 @@
* disabled.
*/
public static boolean isAssistantGestureDisabled(int sysuiStateFlags) {
+ if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
+ sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
+ }
// Disable when in quick settings, screen pinning, immersive, the bouncer is showing,
// or search is disabled
int disableFlags = SYSUI_STATE_SCREEN_PINNING
@@ -205,6 +217,9 @@
|| (sysuiStateFlags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0) {
return false;
}
+ if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
+ sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
+ }
// Disable when in immersive, or the notifications are interactive
int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN
| SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index 7c6a274..59e81cf 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -87,8 +87,7 @@
private void initColors() {
mLockScreenColors[0] = Utils.getColorAttrDefaultColor(getContext(),
com.android.systemui.R.attr.wallpaperTextColor);
- mLockScreenColors[1] = Utils.getColorAttrDefaultColor(getContext(),
- com.android.systemui.R.attr.wallpaperTextColorSecondary);
+ mLockScreenColors[1] = mLockScreenColors[0]; // same color
mView.setColors(mDozingColors, mLockScreenColors);
mView.animateDoze(mIsDozing, false);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
index ca99563..62d3093 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockView.java
@@ -38,7 +38,7 @@
* The time's text color is a gradient that changes its colors based on its controller.
*/
public class AnimatableClockView extends TextView {
- private static final CharSequence FORMAT_12_HOUR = "hh\nmm";
+ private static final CharSequence FORMAT_12_HOUR = "h\nmm";
private static final CharSequence FORMAT_24_HOUR = "HH\nmm";
private static final long ANIM_DURATION = 300;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
index fe64142..26c227d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -118,7 +118,7 @@
mContext,
0 /* requestCode */,
intent,
- PendingIntent.FLAG_UPDATE_CURRENT, UserHandle.SYSTEM);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED, UserHandle.SYSTEM);
mEuiccManager
.switchToSubscription(SubscriptionManager.INVALID_SUBSCRIPTION_ID, callbackIntent);
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index cf576dd..fe0ae33 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -49,6 +49,7 @@
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarOverlayController;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -340,6 +341,7 @@
@Inject Lazy<ProtoTracer> mProtoTracer;
@Inject Lazy<MediaOutputDialogFactory> mMediaOutputDialogFactory;
@Inject Lazy<DeviceConfigProxy> mDeviceConfigProxy;
+ @Inject Lazy<NavigationBarOverlayController> mNavbarButtonsControllerLazy;
@Inject
public Dependency() {
@@ -536,6 +538,8 @@
mProviders.put(MediaOutputDialogFactory.class, mMediaOutputDialogFactory::get);
+ mProviders.put(NavigationBarOverlayController.class, mNavbarButtonsControllerLazy::get);
+
Dependency.setInstance(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index eefae5b..deca14a 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -107,6 +107,7 @@
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
.setPip(mWMComponent.getPip())
.setLegacySplitScreen(mWMComponent.getLegacySplitScreen())
+ .setSplitScreen(mWMComponent.getSplitScreen())
.setOneHanded(mWMComponent.getOneHanded())
.setBubbles(mWMComponent.getBubbles())
.setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
@@ -119,6 +120,7 @@
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
.setPip(Optional.ofNullable(null))
.setLegacySplitScreen(Optional.ofNullable(null))
+ .setSplitScreen(Optional.ofNullable(null))
.setOneHanded(Optional.ofNullable(null))
.setBubbles(Optional.ofNullable(null))
.setHideDisplayCutout(Optional.ofNullable(null))
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index e6ad1cb..13da2b0 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -16,7 +16,7 @@
package com.android.systemui.accessibility;
-import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS;
+import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_ACCESSIBILITY_ACTIONS;
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
@@ -349,7 +349,7 @@
private void handleTakeScreenshot() {
ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN, true, true,
- SCREENSHOT_GLOBAL_ACTIONS, new Handler(Looper.getMainLooper()), null);
+ SCREENSHOT_ACCESSIBILITY_ACTIONS, new Handler(Looper.getMainLooper()), null);
}
private void handleAccessibilityButton() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 9edfee7..055270d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -546,6 +546,12 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
+ // UdfpsController is not BiometricPrompt-specific. It can be active for keyguard or
+ // enrollment.
+ if (mUdfpsController != null) {
+ mUdfpsController.onConfigurationChanged();
+ }
+
// Save the state of the current dialog (buttons showing, etc)
if (mCurrentDialog != null) {
final Bundle savedState = new Bundle();
@@ -567,10 +573,6 @@
promptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL);
}
- if (mUdfpsController != null) {
- mUdfpsController.onConfigurationChanged();
- }
-
showDialog(mCurrentDialogArgs, true /* skipAnimation */, savedState);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 60a14be..1cafb4c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -108,6 +108,8 @@
private boolean mIsOverlayShowing;
// Indicates whether the overlay has been requested.
private boolean mIsOverlayRequested;
+ // Reason the overlay has been requested. See IUdfpsOverlayController for definitions.
+ private int mRequestReason;
// The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
// to turn off high brightness mode. To get around this limitation, the state of the AOD
@@ -118,13 +120,13 @@
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
@Override
- public void showUdfpsOverlay(int sensorId) {
- UdfpsController.this.setShowOverlay(true);
+ public void showUdfpsOverlay(int sensorId, int reason) {
+ UdfpsController.this.showOverlay(reason);
}
@Override
public void hideUdfpsOverlay(int sensorId) {
- UdfpsController.this.setShowOverlay(false);
+ UdfpsController.this.hideOverlay();
}
@Override
@@ -285,17 +287,27 @@
return mView.getSensorRect();
}
- private void setShowOverlay(boolean show) {
- if (show == mIsOverlayRequested) {
+ private void showOverlay(int reason) {
+ if (mIsOverlayRequested) {
return;
}
- mIsOverlayRequested = show;
+ mIsOverlayRequested = true;
+ mRequestReason = reason;
+ updateOverlay();
+ }
+
+ private void hideOverlay() {
+ if (!mIsOverlayRequested) {
+ return;
+ }
+ mIsOverlayRequested = false;
+ mRequestReason = IUdfpsOverlayController.REASON_UNKNOWN;
updateOverlay();
}
private void updateOverlay() {
if (mIsOverlayRequested) {
- showUdfpsOverlay();
+ showUdfpsOverlay(mRequestReason);
} else {
hideUdfpsOverlay();
}
@@ -323,14 +335,15 @@
updateOverlay();
}
- private void showUdfpsOverlay() {
+ private void showUdfpsOverlay(int reason) {
mFgExecutor.execute(() -> {
if (!mIsOverlayShowing) {
try {
Log.v(TAG, "showUdfpsOverlay | adding window");
+ mView.setShowReason(reason);
mWindowManager.addView(mView, computeLayoutParams());
- mIsOverlayShowing = true;
mView.setOnTouchListener(mOnTouchListener);
+ mIsOverlayShowing = true;
} catch (RuntimeException e) {
Log.e(TAG, "showUdfpsOverlay | failed to add window", e);
}
@@ -344,6 +357,7 @@
mFgExecutor.execute(() -> {
if (mIsOverlayShowing) {
Log.v(TAG, "hideUdfpsOverlay | removing window");
+ mView.setShowReason(IUdfpsOverlayController.REASON_UNKNOWN);
mView.setOnTouchListener(null);
// Reset the controller back to its starting state.
onFingerUp();
@@ -420,19 +434,21 @@
}
private void onFingerDown(int x, int y, float minor, float major) {
- mView.setScrimAlpha(computeScrimOpacity());
- mView.showScrimAndDot();
- try {
- if (mHbmSupported) {
+ if (mHbmSupported) {
+ try {
FileWriter fw = new FileWriter(mHbmPath);
fw.write(mHbmEnableCommand);
fw.close();
+ } catch (IOException e) {
+ mView.hideScrimAndDot();
+ Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage());
}
- mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major);
- } catch (IOException e) {
- mView.hideScrimAndDot();
- Log.e(TAG, "onFingerDown | failed to enable HBM: " + e.getMessage());
}
+ mView.setScrimAlpha(computeScrimOpacity());
+ mView.setRunAfterShowingScrimAndDot(() -> {
+ mFingerprintManager.onPointerDown(mSensorProps.sensorId, x, y, minor, major);
+ });
+ mView.showScrimAndDot();
}
private void onFingerUp() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index 663a0da..c2f80d4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -29,10 +30,12 @@
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.IUdfpsOverlayController;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
+import android.util.TypedValue;
import android.view.Surface;
import android.view.View;
import android.view.ViewTreeObserver;
@@ -81,10 +84,15 @@
private float mBurnInOffsetX;
private float mBurnInOffsetY;
+ private int mShowReason;
private boolean mShowScrimAndDot;
private boolean mIsHbmSupported;
@Nullable private String mDebugMessage;
+ // Runnable that will be run after the illumination dot and scrim are shown.
+ // The runnable is reset to null after it's executed once.
+ @Nullable private Runnable mRunAfterShowingScrimAndDot;
+
public UdfpsView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -140,6 +148,13 @@
mSensorProps = properties;
}
+ /**
+ * @param reason See {@link android.hardware.fingerprint.IUdfpsOverlayController}
+ */
+ void setShowReason(int reason) {
+ mShowReason = reason;
+ }
+
@Override
public void dozeTimeTick() {
updateAodPosition();
@@ -208,14 +223,26 @@
// is finished, mTouchableRegion will be used by mInsetsListener to compute the touch
// insets.
mSensorRect.roundOut(mTouchableRegion);
-
-
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Log.v(TAG, "onAttachedToWindow");
+
+ // Retrieve the colors each time, since it depends on day/night mode
+ final TypedValue tv = new TypedValue();
+ mContext.getTheme().resolveAttribute(R.attr.wallpaperTextColor, tv, true);
+ final int authIconColor = mContext.getResources()
+ .getColor(tv.resourceId, mContext.getTheme());
+ final int enrollIconColor = mContext.getColor(R.color.udfps_enroll_icon);
+
+ if (mShowReason == IUdfpsOverlayController.REASON_AUTH) {
+ mFingerprintDrawable.setTint(authIconColor);
+ } else if (mShowReason == IUdfpsOverlayController.REASON_ENROLL) {
+ mFingerprintDrawable.setTint(enrollIconColor);
+ }
+
getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
}
@@ -246,11 +273,21 @@
// draw dot (white circle)
canvas.drawOval(mSensorRect, mSensorPaint);
} else {
+ final boolean isNightMode = (getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_YES) != 0;
+ if (mShowReason == IUdfpsOverlayController.REASON_ENROLL && !isNightMode) {
+ canvas.drawOval(mSensorRect, mSensorPaint);
+ }
// draw fingerprint icon
mFingerprintDrawable.draw(canvas);
}
canvas.restore();
+
+ if (mShowScrimAndDot && mRunAfterShowingScrimAndDot != null) {
+ post(mRunAfterShowingScrimAndDot);
+ mRunAfterShowingScrimAndDot = null;
+ }
}
RectF getSensorRect() {
@@ -266,6 +303,10 @@
postInvalidate();
}
+ void setRunAfterShowingScrimAndDot(Runnable runnable) {
+ mRunAfterShowingScrimAndDot = runnable;
+ }
+
boolean isValidTouch(float x, float y, float pressure) {
// The X and Y coordinates of the sensor's center.
final float cx = mSensorRect.centerX();
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index eea168a..39cbc90 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -26,9 +26,9 @@
import android.os.Message
import android.os.UserHandle
import android.text.TextUtils
+import android.util.IndentingPrintWriter
import android.util.SparseArray
import com.android.internal.annotations.VisibleForTesting
-import com.android.internal.util.IndentingPrintWriter
import com.android.systemui.Dumpable
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
import com.android.systemui.dump.DumpManager
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
index f68388d..40c2386 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
@@ -139,7 +139,6 @@
}
private fun bindButtons() {
- val rootView = requireViewById<ViewGroup>(R.id.controls_management_root)
saveButton = requireViewById<Button>(R.id.done).apply {
isEnabled = false
setText(R.string.save)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
index ad0e7a5..d65481a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
@@ -114,6 +114,7 @@
val controlStatus: ControlStatus
) : ElementWrapper(), ControlInterface by controlStatus
+@Suppress("UNUSED_PARAMETER") // Use function instead of lambda for compile time alloc
private fun nullIconGetter(_a: ComponentName, _b: String): Icon? = null
data class ControlInfoWrapper(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt b/packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
index f9ce636..85e8c60 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
@@ -220,7 +220,7 @@
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
- onMoveItem(viewHolder.adapterPosition, target.adapterPosition)
+ onMoveItem(viewHolder.bindingAdapterPosition, target.bindingAdapterPosition)
return true
}
@@ -228,7 +228,7 @@
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
- if (viewHolder.adapterPosition < dividerPosition) {
+ if (viewHolder.bindingAdapterPosition < dividerPosition) {
return ItemTouchHelper.Callback.makeMovementFlags(MOVEMENT, 0)
} else {
return ItemTouchHelper.Callback.makeMovementFlags(0, 0)
@@ -240,7 +240,7 @@
current: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
- return target.adapterPosition < dividerPosition
+ return target.bindingAdapterPosition < dividerPosition
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index f22fa32..726e2d0 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -56,6 +56,7 @@
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarOverlayController;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.PluginInitializerImpl;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -81,8 +82,8 @@
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.theme.ThemeOverlayApplier;
import com.android.systemui.util.leak.LeakDetector;
-import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.pip.Pip;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -221,6 +222,7 @@
SystemActions systemActions,
@Main Handler mainHandler,
UiEventLogger uiEventLogger,
+ NavigationBarOverlayController navBarOverlayController,
ConfigurationController configurationController) {
return new NavigationBarController(context,
windowManager,
@@ -244,6 +246,7 @@
systemActions,
mainHandler,
uiEventLogger,
+ navBarOverlayController,
configurationController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 612a559..82d313e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -32,6 +32,7 @@
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.Optional;
@@ -63,6 +64,9 @@
Builder setLegacySplitScreen(Optional<LegacySplitScreen> s);
@BindsInstance
+ Builder setSplitScreen(Optional<SplitScreen> s);
+
+ @BindsInstance
Builder setAppPairs(Optional<AppPairs> s);
@BindsInstance
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 7ca8e63..239a77e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -20,6 +20,7 @@
import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
import android.content.Context;
+import android.hardware.SensorPrivacyManager;
import android.os.Handler;
import android.os.PowerManager;
@@ -62,6 +63,10 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyControllerImpl;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
import javax.inject.Named;
@@ -116,6 +121,25 @@
return bC;
}
+ @Provides
+ @SysUISingleton
+ static SensorPrivacyController provideSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ SensorPrivacyController spC = new SensorPrivacyControllerImpl(sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
+ @Provides
+ @SysUISingleton
+ static IndividualSensorPrivacyController provideIndividualSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ IndividualSensorPrivacyController spC = new IndividualSensorPrivacyControllerImpl(
+ sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
@Binds
@SysUISingleton
public abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index c75dc84..ced606c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -26,6 +26,7 @@
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
+import com.android.wm.shell.splitscreen.SplitScreen;
import java.util.Optional;
@@ -73,6 +74,9 @@
Optional<LegacySplitScreen> getLegacySplitScreen();
@WMSingleton
+ Optional<SplitScreen> getSplitScreen();
+
+ @WMSingleton
Optional<AppPairs> getAppPairs();
@WMSingleton
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c6bfcba..f79b991 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1040,7 +1040,7 @@
lockIntent.putExtra(Intent.EXTRA_USER_ID, profileId);
lockIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent lockSender = PendingIntent.getBroadcast(
- mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+ mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
userWhen, lockSender);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java b/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java
index a4d4436..e453653 100644
--- a/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java
+++ b/packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowser.java
@@ -242,7 +242,7 @@
public PendingIntent getAppIntent() {
PackageManager pm = mContext.getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage(mComponentName.getPackageName());
- return PendingIntent.getActivity(mContext, 0, launchIntent, 0);
+ return PendingIntent.getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index f7a4aca..a23b07c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -37,6 +37,7 @@
import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
@@ -136,8 +137,8 @@
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.pip.Pip;
import java.io.PrintWriter;
import java.util.List;
@@ -185,6 +186,7 @@
private final Optional<Recents> mRecentsOptional;
private final SystemActions mSystemActions;
private final Handler mHandler;
+ private final NavigationBarOverlayController mNavbarOverlayController;
private final UiEventLogger mUiEventLogger;
private Bundle mSavedState;
@@ -415,6 +417,7 @@
NotificationRemoteInputManager notificationRemoteInputManager,
SystemActions systemActions,
@Main Handler mainHandler,
+ NavigationBarOverlayController navbarOverlayController,
UiEventLogger uiEventLogger) {
mContext = context;
mWindowManager = windowManager;
@@ -438,6 +441,7 @@
mRecentsOptional = recentsOptional;
mSystemActions = systemActions;
mHandler = mainHandler;
+ mNavbarOverlayController = navbarOverlayController;
mUiEventLogger = uiEventLogger;
}
@@ -814,6 +818,7 @@
mNavigationBarView.setNavigationIconHints(hints);
}
checkBarModes();
+ updateSystemUiStateFlags(-1);
}
@Override
@@ -862,6 +867,13 @@
rotationButtonController.onRotationProposal(rotation, winRotation, isValid);
}
+ @Override
+ public void onRecentsAnimationStateChanged(boolean running) {
+ if (running) {
+ mNavbarOverlayController.setButtonState(/* visible */false, /* force */true);
+ }
+ }
+
/** Restores the appearance and the transient saved state to {@link NavigationBar}. */
public void restoreAppearanceAndTransientState() {
final int barMode = barMode(mTransientShown, mAppearance);
@@ -1305,6 +1317,8 @@
mSysUiFlagsContainer.setFlag(SYSUI_STATE_A11Y_BUTTON_CLICKABLE, clickable)
.setFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable)
.setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isNavBarWindowVisible())
+ .setFlag(SYSUI_STATE_IME_SHOWING,
+ (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0)
.commitUpdate(mDisplayId);
registerAction(clickable, SystemActions.SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON);
registerAction(longClickable, SystemActions.SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 461ab3a..27ea64f8 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -64,8 +64,8 @@
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.pip.Pip;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -107,6 +107,7 @@
private final UiEventLogger mUiEventLogger;
private final Handler mHandler;
private final DisplayManager mDisplayManager;
+ private final NavigationBarOverlayController mNavBarOverlayController;
/** A displayId - nav bar maps. */
@VisibleForTesting
@@ -141,6 +142,7 @@
SystemActions systemActions,
@Main Handler mainHandler,
UiEventLogger uiEventLogger,
+ NavigationBarOverlayController navBarOverlayController,
ConfigurationController configurationController) {
mContext = context;
mWindowManager = windowManager;
@@ -168,6 +170,7 @@
commandQueue.addCallback(this);
configurationController.addCallback(this);
mConfigChanges.applyNewConfig(mContext.getResources());
+ mNavBarOverlayController = navBarOverlayController;
}
@Override
@@ -290,6 +293,7 @@
mNotificationRemoteInputManager,
mSystemActions,
mHandler,
+ mNavBarOverlayController,
mUiEventLogger);
View navigationBarView = navBar.createView(savedState);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
new file mode 100644
index 0000000..c526c5d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.navigationbar;
+
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.view.View;
+
+import com.android.systemui.dagger.SysUISingleton;
+
+import java.util.function.Consumer;
+
+import javax.inject.Inject;
+
+/** Contains logic that deals with showing buttons with navigation bar. */
+@SysUISingleton
+public class NavigationBarOverlayController {
+
+ protected final Context mContext;
+
+ @Inject
+ public NavigationBarOverlayController(Context context) {
+ mContext = context;
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ /**
+ * Initialize the controller with visibility change callback and light/dark icon color.
+ */
+ public void init(Consumer<Boolean> visibilityChangeCallback, @ColorInt int lightIconColor,
+ @ColorInt int darkIconColor) {}
+
+ /**
+ * Set whether the view can be shown.
+ */
+ public void setCanShow(boolean canShow) {}
+
+ /**
+ * Set the buttons visibility.
+ */
+ public void setButtonState(boolean visible, boolean force) {}
+
+ /**
+ * Register necessary listeners, called when NavigationBarView is attached to window.
+ */
+ public void registerListeners() {}
+
+ /**
+ * Unregister listeners, called when navigationBarView is detached from window.
+ */
+ public void unregisterListeners() {}
+
+ /**
+ * Set the dark intensity for all drawables.
+ */
+ public void setDarkIntensity(float darkIntensity) {}
+
+ /**
+ * Return the current view.
+ */
+ public View getCurrentView() {
+ return null;
+ }
+
+ /**
+ * Return the visibility of the view.
+ */
+ public boolean isVisible() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
index c0535b5..b55fa4d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
@@ -192,6 +192,7 @@
buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
}
mView.getRotationButtonController().setDarkIntensity(darkIntensity);
+ Dependency.get(NavigationBarOverlayController.class).setDarkIntensity(darkIntensity);
for (DarkIntensityListener listener : mDarkIntensityListeners) {
listener.onDarkIntensity(darkIntensity);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index d6f0799..e7f2b222 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -92,8 +92,8 @@
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.pip.Pip;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -287,6 +287,13 @@
notifyActiveTouchRegions();
};
+ private final Consumer<Boolean> mNavbarOverlayVisibilityChangeCallback = (visible) -> {
+ if (visible) {
+ mAutoHideController.touchAutoHide();
+ }
+ notifyActiveTouchRegions();
+ };
+
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -327,6 +334,9 @@
isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton,
mRotationButtonListener);
+ Dependency.get(NavigationBarOverlayController.class).init(
+ mNavbarOverlayVisibilityChangeCallback, mLightIconColor, mDarkIconColor);
+
mConfiguration = new Configuration();
mTmpLastConfiguration = new Configuration();
mConfiguration.updateFrom(context.getResources().getConfiguration());
@@ -413,6 +423,11 @@
void onTransientStateChanged(boolean isTransient) {
mEdgeBackGestureHandler.onNavBarTransientStateChanged(isTransient);
+
+ // The visibility of the navigation bar buttons is dependent on the transient state of
+ // the navigation bar.
+ Dependency.get(NavigationBarOverlayController.class).setButtonState(
+ isTransient, /* force */ false);
}
void onBarTransition(int newMode) {
@@ -642,6 +657,7 @@
}
mImeVisible = visible;
mRotationButtonController.getRotationButton().setCanShowRotationButton(!mImeVisible);
+ Dependency.get(NavigationBarOverlayController.class).setCanShow(!mImeVisible);
}
public void setDisabledFlags(int disabledFlags) {
@@ -965,6 +981,11 @@
} else {
updateButtonLocation(getRotateSuggestionButton(), inScreenSpace);
}
+ final NavigationBarOverlayController navBarButtonsController =
+ Dependency.get(NavigationBarOverlayController.class);
+ if (navBarButtonsController.isVisible()) {
+ updateButtonLocation(navBarButtonsController.getCurrentView(), inScreenSpace);
+ }
return mTmpRegion;
}
@@ -1185,8 +1206,10 @@
if (mRotationButtonController != null) {
mRotationButtonController.registerListeners();
}
+ Dependency.get(NavigationBarOverlayController.class).registerListeners();
getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
+ updateNavButtonIcons();
}
@Override
@@ -1200,6 +1223,7 @@
if (mRotationButtonController != null) {
mRotationButtonController.unregisterListeners();
}
+ Dependency.get(NavigationBarOverlayController.class).unregisterListeners();
mEdgeBackGestureHandler.onNavBarDetached();
getViewTreeObserver().removeOnComputeInternalInsetsListener(
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 065920c..a8761a6 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -80,6 +80,7 @@
INVALID_APPWIDGET_ID);
mShowSingleConversation = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
+ setResult(RESULT_CANCELED);
// Finish the configuration activity immediately if a widget is added for multiple
// conversations. If the mAppWidgetId is INVALID, then the activity wasn't launched as a
// widget configuration activity.
@@ -151,10 +152,14 @@
private void finishActivity() {
if (PeopleSpaceUtils.DEBUG) Log.d(TAG, "Widget added!");
mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_ADDED);
+ setActivityResult(RESULT_OK);
+ finish();
+ }
+
+ private void setActivityResult(int result) {
Intent resultValue = new Intent();
resultValue.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId);
- setResult(RESULT_OK, resultValue);
- finish();
+ setResult(result, resultValue);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index 12d5bac..8669a81 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -23,12 +23,12 @@
import android.app.PendingIntent;
import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
-import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.Bitmap;
@@ -72,6 +72,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -129,25 +130,36 @@
throws Exception {
boolean showOnlyPriority = Settings.Global.getInt(context.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 1;
- List<ConversationChannelWrapper> conversations = notificationManager.getConversations(
- true).getList();
- List<PeopleSpaceTile> tiles = getSortedTiles(peopleManager,
- conversations.stream().filter(c -> c.getShortcutInfo() != null).map(
- c -> new PeopleSpaceTile.Builder(c.getShortcutInfo(),
- launcherApps).build()));
+ List<ConversationChannelWrapper> conversations =
+ notificationManager.getConversations(
+ false).getList();
+
+ // Add priority conversations to tiles list.
+ Stream<ShortcutInfo> priorityConversations = conversations.stream()
+ .filter(c -> c.getNotificationChannel() != null
+ && c.getNotificationChannel().isImportantConversation())
+ .map(c -> c.getShortcutInfo());
+ List<PeopleSpaceTile> tiles = getSortedTiles(peopleManager, launcherApps,
+ priorityConversations);
+
+ // Sort and then add recent and non priority conversations to tiles list.
if (!showOnlyPriority) {
if (DEBUG) Log.d(TAG, "Add recent conversations");
- List<ConversationChannel> recentConversations =
+ Stream<ShortcutInfo> nonPriorityConversations = conversations.stream()
+ .filter(c -> c.getNotificationChannel() == null
+ || !c.getNotificationChannel().isImportantConversation())
+ .map(c -> c.getShortcutInfo());
+
+ List<ConversationChannel> recentConversationsList =
peopleManager.getRecentConversations().getList();
+ Stream<ShortcutInfo> recentConversations = recentConversationsList
+ .stream()
+ .map(c -> c.getShortcutInfo());
+
+ Stream<ShortcutInfo> mergedStream = Stream.concat(nonPriorityConversations,
+ recentConversations);
List<PeopleSpaceTile> recentTiles =
- getSortedTiles(peopleManager,
- recentConversations
- .stream()
- .filter(
- c -> c.getShortcutInfo() != null)
- .map(
- c -> new PeopleSpaceTile.Builder(c.getShortcutInfo(),
- launcherApps).build()));
+ getSortedTiles(peopleManager, launcherApps, mergedStream);
tiles.addAll(recentTiles);
}
return tiles;
@@ -282,6 +294,7 @@
)
);
views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
+ views.setBoolean(R.id.content_background, "setClipToOutline", true);
Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
activityIntent.addFlags(
@@ -417,8 +430,11 @@
/** Returns a list sorted by ascending last interaction time from {@code stream}. */
private static List<PeopleSpaceTile> getSortedTiles(IPeopleManager peopleManager,
- Stream<PeopleSpaceTile> stream) {
+ LauncherApps launcherApps,
+ Stream<ShortcutInfo> stream) {
return stream
+ .filter(Objects::nonNull)
+ .map(c -> new PeopleSpaceTile.Builder(c, launcherApps).build())
.filter(c -> shouldKeepConversation(c))
.map(c -> c.toBuilder().setLastInteractionTimestamp(
getLastInteraction(peopleManager, c)).build())
@@ -653,5 +669,4 @@
}
return lookupKeysWithBirthdaysToday;
}
-}
-
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
index 1d2e747..eec69f98 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
@@ -28,7 +28,7 @@
appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
.toList()
.sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
- { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest)
+ { it.second.minOrNull() })) // Sort by "smallest" AppOpp (Location is largest)
types = itemsList.map { it.privacyType }.distinct().sorted()
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index e9207f1..bba8579 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -29,6 +29,7 @@
import com.android.systemui.qs.TouchAnimator.Builder;
import com.android.systemui.qs.TouchAnimator.Listener;
import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -49,7 +50,9 @@
private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows";
public static final float EXPANDED_TILE_DELAY = .86f;
-
+ private static final long QQS_FADE_IN_DURATION = 200L;
+ // Fade out faster than fade in to finish before QQS hides.
+ private static final long QQS_FADE_OUT_DURATION = 50L;
private final ArrayList<View> mAllViews = new ArrayList<>();
/**
@@ -77,6 +80,7 @@
private TouchAnimator mBrightnessAnimator;
private boolean mNeedsAnimatorUpdate = false;
+ private boolean mToShowing;
private boolean mOnKeyguard;
private boolean mAllowFancy;
@@ -133,6 +137,18 @@
}
}
+ void startAlphaAnimation(boolean show) {
+ if (show == mToShowing) {
+ return;
+ }
+ mToShowing = show;
+ if (show) {
+ CrossFadeHelper.fadeIn(mQs.getView(), QQS_FADE_IN_DURATION, 0 /* delay */);
+ } else {
+ CrossFadeHelper.fadeOut(mQs.getView(), QQS_FADE_OUT_DURATION, 0 /* delay */,
+ null /* endRunnable */);
+ }
+ }
/**
* Sets whether or not the keyguard is currently being shown with a collapsed header.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 16e9590..562ac64 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -91,6 +91,11 @@
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
void onMediaVisibilityChanged(boolean qsVisible) {
mAnimateBottomOnNextLayout = qsVisible;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index dbdd04a..9a0827d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -186,7 +186,7 @@
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
boolean sizeChanged = (oldTop - oldBottom) != (top - bottom);
if (sizeChanged) {
- setQsExpansion(mLastQSExpansion, mLastQSExpansion);
+ setQsExpansion(mLastQSExpansion, mLastHeaderTranslation);
}
});
}
@@ -391,6 +391,9 @@
@Override
public void setQsExpansion(float expansion, float headerTranslation) {
if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation);
+ if (mQSAnimator != null) {
+ mQSAnimator.startAlphaAnimation(headerTranslation == 0 /* show */);
+ }
mContainer.setExpansion(expansion);
final float translationScaleY = expansion - 1;
boolean onKeyguardAndExpanded = isKeyguardShowing() && !mShowCollapsedOnKeyguard;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index ba71fa6..9b3775e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -30,6 +30,7 @@
import com.android.systemui.qs.tiles.AirplaneModeTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
import com.android.systemui.qs.tiles.BluetoothTile;
+import com.android.systemui.qs.tiles.CameraToggleTile;
import com.android.systemui.qs.tiles.CastTile;
import com.android.systemui.qs.tiles.CellularTile;
import com.android.systemui.qs.tiles.ColorInversionTile;
@@ -39,6 +40,7 @@
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.InternetTile;
import com.android.systemui.qs.tiles.LocationTile;
+import com.android.systemui.qs.tiles.MicrophoneToggleTile;
import com.android.systemui.qs.tiles.NfcTile;
import com.android.systemui.qs.tiles.NightDisplayTile;
import com.android.systemui.qs.tiles.ReduceBrightColorsTile;
@@ -83,6 +85,8 @@
private final Provider<UiModeNightTile> mUiModeNightTileProvider;
private final Provider<ScreenRecordTile> mScreenRecordTileProvider;
private final Provider<ReduceBrightColorsTile> mReduceBrightColorsTileProvider;
+ private final Provider<CameraToggleTile> mCameraToggleTileProvider;
+ private final Provider<MicrophoneToggleTile> mMicrophoneToggleTileProvider;
private final Lazy<QSHost> mQsHostLazy;
private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
@@ -115,7 +119,9 @@
Provider<GarbageMonitor.MemoryTile> memoryTileProvider,
Provider<UiModeNightTile> uiModeNightTileProvider,
Provider<ScreenRecordTile> screenRecordTileProvider,
- Provider<ReduceBrightColorsTile> reduceBrightColorsTileProvider) {
+ Provider<ReduceBrightColorsTile> reduceBrightColorsTileProvider,
+ Provider<CameraToggleTile> cameraToggleTileProvider,
+ Provider<MicrophoneToggleTile> microphoneToggleTileProvider) {
mQsHostLazy = qsHostLazy;
mCustomTileBuilderProvider = customTileBuilderProvider;
@@ -143,6 +149,8 @@
mUiModeNightTileProvider = uiModeNightTileProvider;
mScreenRecordTileProvider = screenRecordTileProvider;
mReduceBrightColorsTileProvider = reduceBrightColorsTileProvider;
+ mCameraToggleTileProvider = cameraToggleTileProvider;
+ mMicrophoneToggleTileProvider = microphoneToggleTileProvider;
}
public QSTile createTile(String tileSpec) {
@@ -198,6 +206,10 @@
return mScreenRecordTileProvider.get();
case "reduce_brightness":
return mReduceBrightColorsTileProvider.get();
+ case "cameratoggle":
+ return mCameraToggleTileProvider.get();
+ case "mictoggle":
+ return mMicrophoneToggleTileProvider.get();
}
// Custom tiles
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
new file mode 100644
index 0000000..98740a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+
+import static com.android.systemui.DejankUtils.whitelistIpcs;
+
+import android.annotation.StringRes;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.DeviceConfig;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+
+import javax.inject.Inject;
+
+public class CameraToggleTile extends SensorPrivacyToggleTile {
+
+ @Inject
+ protected CameraToggleTile(QSHost host,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger,
+ IndividualSensorPrivacyController sensorPrivacyController) {
+ super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
+ activityStarter, qsLogger, sensorPrivacyController);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return /*getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
+ && */whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ "camera_toggle_enabled",
+ false));
+ }
+
+ @Override
+ public @DrawableRes int getIconRes() {
+ return R.drawable.ic_camera_blocked;
+ }
+
+ @Override
+ public @NonNull CharSequence getTileLabel() {
+ return mContext.getString(R.string.quick_settings_camera_label);
+ }
+
+ @Override
+ public int getSensorId() {
+ return CAMERA;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 86524f5..17866e2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -58,6 +58,8 @@
/** Quick settings tile: Internet **/
public class InternetTile extends QSTileImpl<SignalState> {
private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
+ private static final Intent INTERNET_PANEL =
+ new Intent(Settings.Panel.ACTION_INTERNET_CONNECTIVITY);
protected final NetworkController mController;
private final DataUsageController mDataController;
@@ -102,7 +104,7 @@
@Override
protected void handleClick() {
- mActivityStarter.postStartActivityDismissingKeyguard(WIFI_SETTINGS, 0);
+ mActivityStarter.postStartActivityDismissingKeyguard(INTERNET_PANEL, 0);
}
@Override
@@ -138,6 +140,7 @@
}
private static final class WifiCallbackInfo {
+ boolean mAirplaneModeEnabled;
boolean mEnabled;
boolean mConnected;
int mWifiSignalIconId;
@@ -147,11 +150,15 @@
String mWifiSignalContentDescription;
boolean mIsTransient;
public String mStatusLabel;
+ boolean mNoDefaultNetwork;
+ boolean mNoValidatedNetwork;
+ boolean mNoNetworksAvailable;
@Override
public String toString() {
return new StringBuilder("WifiCallbackInfo[")
- .append("mEnabled=").append(mEnabled)
+ .append("mAirplaneModeEnabled=").append(mAirplaneModeEnabled)
+ .append(",mEnabled=").append(mEnabled)
.append(",mConnected=").append(mConnected)
.append(",mWifiSignalIconId=").append(mWifiSignalIconId)
.append(",mSsid=").append(mSsid)
@@ -159,6 +166,9 @@
.append(",mActivityOut=").append(mActivityOut)
.append(",mWifiSignalContentDescription=").append(mWifiSignalContentDescription)
.append(",mIsTransient=").append(mIsTransient)
+ .append(",mNoDefaultNetwork=").append(mNoDefaultNetwork)
+ .append(",mNoValidatedNetwork=").append(mNoValidatedNetwork)
+ .append(",mNoNetworksAvailable=").append(mNoNetworksAvailable)
.append(']').toString();
}
}
@@ -173,6 +183,9 @@
boolean mNoSim;
boolean mRoaming;
boolean mMultipleSubs;
+ boolean mNoDefaultNetwork;
+ boolean mNoValidatedNetwork;
+ boolean mNoNetworksAvailable;
@Override
public String toString() {
@@ -186,6 +199,9 @@
.append(",mNoSim=").append(mNoSim)
.append(",mRoaming=").append(mRoaming)
.append(",mMultipleSubs=").append(mMultipleSubs)
+ .append(",mNoDefaultNetwork=").append(mNoDefaultNetwork)
+ .append(",mNoValidatedNetwork=").append(mNoValidatedNetwork)
+ .append(",mNoNetworksAvailable=").append(mNoNetworksAvailable)
.append(']').toString();
}
}
@@ -198,7 +214,7 @@
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description, boolean isTransient,
String statusLabel) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
+ if (DEBUG) {
Log.d(TAG, "setWifiIndicators: "
+ "enabled = " + enabled + ","
+ "statusIcon = " + (statusIcon == null ? "" : statusIcon.toString()) + ","
@@ -209,13 +225,20 @@
+ "isTransient = " + isTransient + ","
+ "statusLabel = " + statusLabel);
}
+ // When airplane mode is enabled, we need to refresh the Internet Tile even if the WiFi
+ // is not the default network.
+ if (qsIcon == null && !mWifiInfo.mAirplaneModeEnabled) {
+ return;
+ }
+ if (qsIcon != null) {
+ mWifiInfo.mConnected = qsIcon.visible;
+ mWifiInfo.mWifiSignalIconId = qsIcon.icon;
+ mWifiInfo.mWifiSignalContentDescription = qsIcon.contentDescription;
+ }
mWifiInfo.mEnabled = enabled;
- mWifiInfo.mConnected = qsIcon.visible;
- mWifiInfo.mWifiSignalIconId = qsIcon.icon;
mWifiInfo.mSsid = description;
mWifiInfo.mActivityIn = activityIn;
mWifiInfo.mActivityOut = activityOut;
- mWifiInfo.mWifiSignalContentDescription = qsIcon.contentDescription;
mWifiInfo.mIsTransient = isTransient;
mWifiInfo.mStatusLabel = statusLabel;
refreshState(mWifiInfo);
@@ -227,7 +250,7 @@
CharSequence typeContentDescription,
CharSequence typeContentDescriptionHtml, CharSequence description,
boolean isWide, int subId, boolean roaming) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
+ if (DEBUG) {
Log.d(TAG, "setMobileDataIndicators: "
+ "statusIcon = " + (statusIcon == null ? "" : statusIcon.toString()) + ","
+ "qsIcon = " + (qsIcon == null ? "" : qsIcon.toString()) + ","
@@ -246,7 +269,8 @@
// Not data sim, don't display.
return;
}
- mCellularInfo.mDataSubscriptionName = mController.getMobileDataNetworkName();
+ mCellularInfo.mDataSubscriptionName =
+ description == null ? mController.getMobileDataNetworkName() : description;
mCellularInfo.mDataContentDescription =
(description != null) ? typeContentDescriptionHtml : null;
mCellularInfo.mMobileSignalIconId = qsIcon.icon;
@@ -259,7 +283,7 @@
@Override
public void setNoSims(boolean show, boolean simDetected) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
+ if (DEBUG) {
Log.d(TAG, "setNoSims: "
+ "show = " + show + ","
+ "simDetected = " + simDetected);
@@ -274,18 +298,36 @@
@Override
public void setIsAirplaneMode(IconState icon) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "InternetTile-setIsAirplaneMode: "
+ if (DEBUG) {
+ Log.d(TAG, "setIsAirplaneMode: "
+ "icon = " + (icon == null ? "" : icon.toString()));
}
mCellularInfo.mAirplaneModeEnabled = icon.visible;
+ mWifiInfo.mAirplaneModeEnabled = icon.visible;
refreshState(mCellularInfo);
}
+
+ @Override
+ public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
+ boolean noNetworksAvailable) {
+ if (DEBUG) {
+ Log.d(TAG, "setConnectivityStatus: "
+ + "noDefaultNetwork = " + noDefaultNetwork + ","
+ + "noValidatedNetwork = " + noValidatedNetwork + ","
+ + "noNetworksAvailable = " + noNetworksAvailable);
+ }
+ mCellularInfo.mNoDefaultNetwork = noDefaultNetwork;
+ mCellularInfo.mNoValidatedNetwork = noValidatedNetwork;
+ mCellularInfo.mNoNetworksAvailable = noNetworksAvailable;
+ mWifiInfo.mNoDefaultNetwork = noDefaultNetwork;
+ mWifiInfo.mNoValidatedNetwork = noValidatedNetwork;
+ mWifiInfo.mNoNetworksAvailable = noNetworksAvailable;
+ refreshState(mWifiInfo);
+ }
}
@Override
protected void handleUpdateState(SignalState state, Object arg) {
- Log.d(TAG, "handleUpdateState: " + "arg = " + arg);
if (arg instanceof CellularCallbackInfo) {
mLastTileState = 0;
handleUpdateCellularState(state, arg);
@@ -306,6 +348,9 @@
private void handleUpdateWifiState(SignalState state, Object arg) {
WifiCallbackInfo cb = (WifiCallbackInfo) arg;
+ if (DEBUG) {
+ Log.d(TAG, "handleUpdateWifiState: " + "WifiCallbackInfo = " + cb.toString());
+ }
boolean wifiConnected = cb.mEnabled && (cb.mWifiSignalIconId > 0) && (cb.mSsid != null);
boolean wifiNotConnected = (cb.mWifiSignalIconId > 0) && (cb.mSsid == null);
boolean enabledChanging = state.value != cb.mEnabled;
@@ -326,25 +371,44 @@
final StringBuffer minimalContentDescription = new StringBuffer();
final StringBuffer minimalStateDescription = new StringBuffer();
final Resources r = mContext.getResources();
- // TODO(b/174753536): Use the new "Internet" string as state.label once available.
- if (cb.mIsTransient) {
+ state.label = r.getString(R.string.quick_settings_internet_label);
+ if (cb.mAirplaneModeEnabled) {
+ if (!state.value) {
+ state.state = Tile.STATE_UNAVAILABLE;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_airplane);
+ state.secondaryLabel = r.getString(R.string.status_bar_airplane);
+ } else if (!wifiConnected) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_airplane);
+ if (cb.mNoNetworksAvailable) {
+ state.secondaryLabel =
+ r.getString(R.string.quick_settings_networks_unavailable);
+ } else {
+ state.secondaryLabel =
+ r.getString(R.string.quick_settings_networks_available);
+ }
+ } else {
+ state.icon = ResourceIcon.get(cb.mWifiSignalIconId);
+ state.label = r.getString(R.string.quick_settings_airplane_safe_label);
+ }
+ } else if (cb.mNoDefaultNetwork && cb.mNoNetworksAvailable) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable);
+ state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable);
+ } else if (cb.mNoValidatedNetwork && !cb.mNoNetworksAvailable) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_available);
+ state.secondaryLabel = r.getString(R.string.quick_settings_networks_available);
+ } else if (cb.mIsTransient) {
state.icon = ResourceIcon.get(
com.android.internal.R.drawable.ic_signal_wifi_transient_animation);
- state.label = r.getString(R.string.quick_settings_internet_label);
} else if (!state.value) {
state.slash.isSlashed = true;
state.state = Tile.STATE_INACTIVE;
state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_DISABLED);
- state.label = r.getString(R.string.quick_settings_internet_label);
} else if (wifiConnected) {
state.icon = ResourceIcon.get(cb.mWifiSignalIconId);
- state.label = r.getString(R.string.quick_settings_internet_label);
} else if (wifiNotConnected) {
state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK);
- state.label = r.getString(R.string.quick_settings_internet_label);
} else {
state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK);
- state.label = r.getString(R.string.quick_settings_internet_label);
}
minimalContentDescription.append(
mContext.getString(R.string.quick_settings_internet_label)).append(",");
@@ -366,34 +430,37 @@
private void handleUpdateCellularState(SignalState state, Object arg) {
CellularCallbackInfo cb = (CellularCallbackInfo) arg;
+ if (DEBUG) {
+ Log.d(TAG, "handleUpdateCellularState: " + "CellularCallbackInfo = " + cb.toString());
+ }
final Resources r = mContext.getResources();
// TODO(b/174753536): Use the new "Internet" string as state.label once available.
state.label = r.getString(R.string.quick_settings_internet_label);
+ state.state = Tile.STATE_ACTIVE;
boolean mobileDataEnabled = mDataController.isMobileDataSupported()
&& mDataController.isMobileDataEnabled();
state.value = mobileDataEnabled;
state.activityIn = mobileDataEnabled && cb.mActivityIn;
state.activityOut = mobileDataEnabled && cb.mActivityOut;
state.expandedAccessibilityClassName = Switch.class.getName();
- if (cb.mNoSim) {
- state.icon = ResourceIcon.get(R.drawable.ic_qs_no_sim);
- } else {
- state.icon = new SignalIcon(cb.mMobileSignalIconId);
- }
- if (cb.mNoSim) {
+ if (cb.mAirplaneModeEnabled && cb.mNoDefaultNetwork) {
state.state = Tile.STATE_UNAVAILABLE;
- state.secondaryLabel = r.getString(R.string.keyguard_missing_sim_message_short);
- } else if (cb.mAirplaneModeEnabled) {
- state.state = Tile.STATE_UNAVAILABLE;
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_airplane);
state.secondaryLabel = r.getString(R.string.status_bar_airplane);
- } else if (mobileDataEnabled) {
- state.state = Tile.STATE_ACTIVE;
+ } else if (cb.mNoDefaultNetwork && cb.mNoNetworksAvailable) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable);
+ state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable);
+ } else if (cb.mNoValidatedNetwork && !cb.mNoNetworksAvailable) {
+ state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_available);
+ state.secondaryLabel = r.getString(R.string.quick_settings_networks_available);
+ } else {
+ if (cb.mAirplaneModeEnabled) {
+ state.label = r.getString(R.string.quick_settings_airplane_safe_label);
+ }
+ state.icon = new SignalIcon(cb.mMobileSignalIconId);
state.secondaryLabel = appendMobileDataType(cb.mDataSubscriptionName,
getMobileDataContentName(cb));
- } else {
- state.state = Tile.STATE_INACTIVE;
- state.secondaryLabel = r.getString(R.string.cell_data_off);
}
state.contentDescription = state.label;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
new file mode 100644
index 0000000..8cc0d7b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+
+import static com.android.systemui.DejankUtils.whitelistIpcs;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.DeviceConfig;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+
+import javax.inject.Inject;
+
+public class MicrophoneToggleTile extends SensorPrivacyToggleTile {
+
+ @Inject
+ protected MicrophoneToggleTile(QSHost host,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger,
+ IndividualSensorPrivacyController sensorPrivacyController) {
+ super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
+ activityStarter, qsLogger, sensorPrivacyController);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ "mic_toggle_enabled",
+ false));
+ }
+
+ @Override
+ public @DrawableRes int getIconRes() {
+ return R.drawable.ic_mic_blocked;
+ }
+
+ @Override
+ public @NonNull CharSequence getTileLabel() {
+ return mContext.getString(R.string.quick_settings_mic_label);
+ }
+
+ @Override
+ public int getSensorId() {
+ return MICROPHONE;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
new file mode 100644
index 0000000..12205d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import android.content.Intent;
+import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.os.Handler;
+import android.os.Looper;
+import android.service.quicksettings.Tile;
+import android.widget.Switch;
+
+import androidx.annotation.DrawableRes;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+
+/**
+ * Superclass to toggle individual sensor privacy via quick settings tiles
+ */
+public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanState> implements
+ IndividualSensorPrivacyController.Callback {
+
+ private IndividualSensorPrivacyController mSensorPrivacyController;
+
+ /**
+ * @return Id of the sensor that will be toggled
+ */
+ public abstract @IndividualSensor int getSensorId();
+
+ /**
+ * @return icon for the QS tile
+ */
+ public abstract @DrawableRes int getIconRes();
+
+ protected SensorPrivacyToggleTile(QSHost host,
+ @Background Looper backgroundLooper,
+ @Main Handler mainHandler,
+ MetricsLogger metricsLogger,
+ StatusBarStateController statusBarStateController,
+ ActivityStarter activityStarter,
+ QSLogger qsLogger,
+ IndividualSensorPrivacyController sensorPrivacyController) {
+ super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
+ activityStarter, qsLogger);
+ mSensorPrivacyController = sensorPrivacyController;
+ mSensorPrivacyController.observe(getLifecycle(), this);
+ }
+
+ @Override
+ public BooleanState newTileState() {
+ return new BooleanState();
+ }
+
+ @Override
+ protected void handleClick() {
+ mSensorPrivacyController.setSensorBlocked(getSensorId(),
+ !mSensorPrivacyController.isSensorBlocked(getSensorId()));
+ }
+
+ @Override
+ protected void handleUpdateState(BooleanState state, Object arg) {
+ boolean isBlocked = arg == null ? mSensorPrivacyController.isSensorBlocked(getSensorId())
+ : (boolean) arg;
+
+ state.icon = ResourceIcon.get(getIconRes());
+ state.state = isBlocked ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+ state.value = isBlocked;
+ state.label = getTileLabel();
+ state.handlesLongClick = false;
+ state.contentDescription = state.label;
+ state.expandedAccessibilityClassName = Switch.class.getName();
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return 0;
+ }
+
+ @Override
+ public Intent getLongClickIntent() {
+ return null;
+ }
+
+ @Override
+ public void onSensorBlockedChanged(int sensor, boolean blocked) {
+ if (sensor == getSensorId()) {
+ refreshState(blocked);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 19eac77..a6fd011 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -307,6 +307,9 @@
boolean activityIn, boolean activityOut, String description, boolean isTransient,
String statusLabel) {
if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
+ if (qsIcon == null) {
+ return;
+ }
mInfo.enabled = enabled;
mInfo.connected = qsIcon.visible;
mInfo.wifiSignalIconId = qsIcon.icon;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index a60c241..7d57799 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -38,6 +38,7 @@
import android.app.ExitTransitionCoordinator;
import android.app.ExitTransitionCoordinator.ExitTransitionCallbacks;
import android.app.Notification;
+import android.app.WindowContext;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -165,7 +166,7 @@
// From WizardManagerHelper.java
private static final String SETTINGS_SECURE_USER_SETUP_COMPLETE = "user_setup_complete";
- private final Context mContext;
+ private final WindowContext mContext;
private final ScreenshotNotificationsController mNotificationsController;
private final ScreenshotSmartActions mScreenshotSmartActions;
private final UiEventLogger mUiEventLogger;
@@ -240,7 +241,7 @@
final DisplayManager dm = requireNonNull(context.getSystemService(DisplayManager.class));
final Display display = dm.getDisplay(DEFAULT_DISPLAY);
final Context displayContext = context.createDisplayContext(display);
- mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null);
+ mContext = (WindowContext) displayContext.createWindowContext(TYPE_SCREENSHOT, null);
mWindowManager = mContext.getSystemService(WindowManager.class);
mAccessibilityManager = AccessibilityManager.getInstance(mContext);
@@ -352,6 +353,13 @@
}
/**
+ * Release the constructed window context.
+ */
+ void releaseContext() {
+ mContext.release();
+ }
+
+ /**
* Update resources on configuration change. Reinflate for theme/color changes.
*/
private void reloadAssets() {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
index db5a494..6cdf6ab 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
@@ -82,7 +82,7 @@
dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
if (intent != null) {
final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
- mContext, 0, intent, 0, null, UserHandle.CURRENT);
+ mContext, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED, null, UserHandle.CURRENT);
b.setContentIntent(pendingIntent);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index 357702a..41c2098 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -63,6 +63,7 @@
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -117,6 +118,7 @@
private final DisplayMetrics mDisplayMetrics;
private final float mCornerSizeX;
private final float mDismissDeltaY;
+ private final AccessibilityManager mAccessibilityManager;
private int mNavMode;
private int mLeftInset;
@@ -178,6 +180,8 @@
mDisplayMetrics = new DisplayMetrics();
mContext.getDisplay().getRealMetrics(mDisplayMetrics);
+
+ mAccessibilityManager = AccessibilityManager.getInstance(mContext);
}
/**
@@ -331,8 +335,10 @@
mScreenshotPreview.setScaleX(currentScale);
mScreenshotPreview.setScaleY(currentScale);
- mDismissButton.setAlpha(0);
- mDismissButton.setVisibility(View.VISIBLE);
+ if (mAccessibilityManager.isEnabled()) {
+ mDismissButton.setAlpha(0);
+ mDismissButton.setVisibility(View.VISIBLE);
+ }
AnimatorSet dropInAnimation = new AnimatorSet();
ValueAnimator flashInAnimator = ValueAnimator.ofFloat(0, 1);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index c2b20d3..c33bbc5 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -123,6 +123,9 @@
@Override
public void onDestroy() {
super.onDestroy();
+ if (mScreenshot != null) {
+ mScreenshot.releaseContext();
+ }
if (DEBUG_SERVICE) {
Log.d(TAG, "onDestroy");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index f758db8..9d52fe5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -19,11 +19,11 @@
import android.app.ActivityManager
import android.content.res.Resources
import android.os.SystemProperties
+import android.util.IndentingPrintWriter
import android.util.MathUtils
import android.view.SurfaceControl
import android.view.ViewRootImpl
import androidx.annotation.VisibleForTesting
-import com.android.internal.util.IndentingPrintWriter
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index bb76ac0..ca3923f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -504,7 +504,7 @@
// TODO: Should this really be for all users? It appears that inactive users
// can't have active sessions, which would mean it is fine.
final List<MediaController> sessions =
- mMediaSessionManager.getActiveSessionsForUser(null, UserHandle.USER_ALL);
+ mMediaSessionManager.getActiveSessionsForUser(null, UserHandle.ALL);
for (MediaController aController : sessions) {
// now to see if we have one like this
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 01aa53f..ead6d32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -21,6 +21,7 @@
import android.animation.ValueAnimator
import android.app.WallpaperManager
import android.os.SystemClock
+import android.util.IndentingPrintWriter
import android.util.Log
import android.util.MathUtils
import android.view.Choreographer
@@ -29,7 +30,6 @@
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
-import com.android.internal.util.IndentingPrintWriter
import com.android.systemui.Dumpable
import com.android.systemui.Interpolators
import com.android.systemui.dagger.SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 45e8098..88b9c6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -233,7 +233,8 @@
@Override
public void onAnimationStart(Animator animation) {
- InteractionJankMonitor.getInstance().begin(CUJ_NOTIFICATION_APP_START);
+ InteractionJankMonitor.getInstance().begin(mSourceNotification,
+ CUJ_NOTIFICATION_APP_START);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 86ebc6b..724921b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -762,7 +762,8 @@
@Override
public void onAnimationStart(Animator animation) {
mWasCancelled = false;
- InteractionJankMonitor.getInstance().begin(getCujType(isAppearing));
+ InteractionJankMonitor.getInstance().begin(ActivatableNotificationView.this,
+ getCujType(isAppearing));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index e43130f..1a2550b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -642,9 +642,8 @@
BUBBLE_PREFERENCE_SELECTED);
}
if (mBubblesManagerOptional.isPresent()) {
- post(() -> {
- mBubblesManagerOptional.get().onUserChangedImportance(mEntry);
- });
+ post(() -> mBubblesManagerOptional.get()
+ .onUserSetImportantConversation(mEntry));
}
}
mChannelToUpdate.setImportance(Math.max(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 2c501cb..b5963ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -77,6 +77,7 @@
private Runnable mOnPulseHeightChangedListener;
private ExpandableNotificationRow mTrackedHeadsUpRow;
private float mAppearFraction;
+ private boolean mIsShadeOpening;
/** Tracks the state from AlertingNotificationManager#hasNotifications() */
private boolean mHasAlertEntries;
@@ -96,6 +97,14 @@
mBaseZHeight = getBaseHeight(mZDistanceBetweenElements);
}
+ void setIsShadeOpening(boolean isOpening) {
+ mIsShadeOpening = isOpening;
+ }
+
+ public boolean isShadeOpening() {
+ return mIsShadeOpening;
+ }
+
private static int getZDistanceBetweenElements(Context context) {
return Math.max(1, context.getResources()
.getDimensionPixelSize(R.dimen.z_distance_between_notifications));
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 9e8385b..6abbc6b 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
@@ -550,6 +550,10 @@
}
}
+ void setIsShadeOpening(boolean isOpening) {
+ mAmbientState.setIsShadeOpening(isOpening);
+ }
+
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
protected void onFinishInflate() {
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 e332f18..5126f55 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
@@ -271,6 +271,10 @@
}
};
+ public void setIsShadeOpening(boolean isOpening) {
+ mView.setIsShadeOpening(isOpening);
+ }
+
private final OnMenuEventListener mMenuEventListener = new OnMenuEventListener() {
@Override
public void onMenuClicked(
@@ -1553,7 +1557,8 @@
// In the intercept we only start tracing when it's not a down (otherwise that down
// would be duplicated when intercepted).
if (scrollWantsIt && ev.getActionMasked() != MotionEvent.ACTION_DOWN) {
- InteractionJankMonitor.getInstance().begin(CUJ_NOTIFICATION_SHADE_SCROLL_FLING);
+ InteractionJankMonitor.getInstance().begin(mView,
+ CUJ_NOTIFICATION_SHADE_SCROLL_FLING);
}
return swipeWantsIt || scrollWantsIt || expandWantsIt;
}
@@ -1619,7 +1624,7 @@
case MotionEvent.ACTION_DOWN:
if (scrollerWantsIt) {
InteractionJankMonitor.getInstance()
- .begin(CUJ_NOTIFICATION_SHADE_SCROLL_FLING);
+ .begin(mView, CUJ_NOTIFICATION_SHADE_SCROLL_FLING);
}
break;
case MotionEvent.ACTION_UP:
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 ba08e76..d132abe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -129,7 +129,6 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.util.InjectionInflationController;
import com.android.wm.shell.animation.FlingAnimationUtils;
import java.io.FileDescriptor;
@@ -266,8 +265,7 @@
&& mAuthController.getUdfpsRegion() != null
&& mAuthController.isUdfpsEnrolled(
KeyguardUpdateMonitor.getCurrentUser())) {
- LayoutInflater.from(mView.getContext())
- .inflate(R.layout.disabled_udfps_view, mView);
+ mLayoutInflater.inflate(R.layout.disabled_udfps_view, mView);
mDisabledUdfpsController = new DisabledUdfpsController(
mView.findViewById(R.id.disabled_udfps_view),
mStatusBarStateController,
@@ -279,7 +277,7 @@
}
};
- private final InjectionInflationController mInjectionInflationController;
+ private final LayoutInflater mLayoutInflater;
private final PowerManager mPowerManager;
private final AccessibilityManager mAccessibilityManager;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
@@ -523,7 +521,7 @@
@Inject
public NotificationPanelViewController(NotificationPanelView view,
@Main Resources resources,
- InjectionInflationController injectionInflationController,
+ LayoutInflater layoutInflater,
NotificationWakeUpCoordinator coordinator, PulseExpansionHandler pulseExpansionHandler,
DynamicPrivacyController dynamicPrivacyController,
KeyguardBypassController bypassController, FalsingManager falsingManager,
@@ -568,7 +566,7 @@
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
mQSDetailDisplayer = qsDetailDisplayer;
mView.setWillNotDraw(!DEBUG);
- mInjectionInflationController = injectionInflationController;
+ mLayoutInflater = layoutInflater;
mFalsingManager = falsingManager;
mFalsingCollector = falsingCollector;
mPowerManager = powerManager;
@@ -774,8 +772,7 @@
KeyguardStatusView keyguardStatusView = mView.findViewById(R.id.keyguard_status_view);
int index = mView.indexOfChild(keyguardStatusView);
mView.removeView(keyguardStatusView);
- keyguardStatusView = (KeyguardStatusView) mInjectionInflationController.injectable(
- LayoutInflater.from(mView.getContext())).inflate(
+ keyguardStatusView = (KeyguardStatusView) mLayoutInflater.inflate(
R.layout.keyguard_status_view, mView, false);
mView.addView(keyguardStatusView, index);
@@ -786,8 +783,7 @@
index = mView.indexOfChild(mKeyguardBottomArea);
mView.removeView(mKeyguardBottomArea);
KeyguardBottomAreaView oldBottomArea = mKeyguardBottomArea;
- mKeyguardBottomArea = (KeyguardBottomAreaView) mInjectionInflationController.injectable(
- LayoutInflater.from(mView.getContext())).inflate(
+ mKeyguardBottomArea = (KeyguardBottomAreaView) mLayoutInflater.inflate(
R.layout.keyguard_bottom_area, mView, false);
mKeyguardBottomArea.initFrom(oldBottomArea);
mView.addView(mKeyguardBottomArea, index);
@@ -1266,7 +1262,7 @@
private void traceQsJank(boolean startTracing, boolean wasCancelled) {
InteractionJankMonitor monitor = InteractionJankMonitor.getInstance();
if (startTracing) {
- monitor.begin(CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
+ monitor.begin(mView, CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
} else {
if (wasCancelled) {
monitor.cancel(CUJ_NOTIFICATION_SHADE_QS_EXPAND_COLLAPSE);
@@ -1479,7 +1475,7 @@
return;
}
mExpectingSynthesizedDown = true;
- InteractionJankMonitor.getInstance().begin(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
+ InteractionJankMonitor.getInstance().begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
onTrackingStarted();
updatePanelExpanded();
}
@@ -2412,6 +2408,11 @@
}
@Override
+ protected void setIsShadeOpening(boolean isOpening) {
+ mNotificationStackScrollLayoutController.setIsShadeOpening(isOpening);
+ }
+
+ @Override
protected void setOverExpansion(float overExpansion, boolean isPixels) {
if (mConflictingQsExpansionGesture || mQsExpandImmediate) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java
index 619aadb..af595b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java
@@ -146,7 +146,6 @@
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setWillNotDraw(!DEBUG);
- InteractionJankMonitor.getInstance().init(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index c106518..a1112dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -52,6 +52,9 @@
public void go(int state) {
if (DEBUG) LOG("go state: %d -> %d", mState, state);
mState = state;
+ if (mPanel != null) {
+ mPanel.setIsShadeOpening(state == STATE_OPENING);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 8ed9710..da82986 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -360,7 +360,8 @@
protected void startExpandMotion(float newX, float newY, boolean startTracking,
float expandedHeight) {
if (!mHandlingPointerUp) {
- InteractionJankMonitor.getInstance().begin(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
+ InteractionJankMonitor.getInstance().begin(mView,
+ CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
}
mInitialOffsetOnTouch = expandedHeight;
mInitialTouchY = newY;
@@ -739,6 +740,8 @@
*/
protected abstract boolean isTrackingBlocked();
+ protected abstract void setIsShadeOpening(boolean isShadeOpening);
+
protected abstract void setOverExpansion(float overExpansion, boolean isPixels);
protected abstract void onHeightUpdated(float expandedHeight);
@@ -862,7 +865,7 @@
mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
if (mAnimateAfterExpanding) {
notifyExpandingStarted();
- InteractionJankMonitor.getInstance().begin(
+ InteractionJankMonitor.getInstance().begin(mView,
CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
fling(0, true /* expand */);
} else {
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 f8e361f..f1b3cc5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -370,13 +370,15 @@
if (mKeyguardUpdateMonitor.needsSlowUnlockTransition() && mState == ScrimState.UNLOCKED) {
mAnimationDelay = StatusBar.FADE_KEYGUARD_START_DELAY;
scheduleUpdate();
- } else if ((!mDozeParameters.getAlwaysOn() && oldState == ScrimState.AOD)
+ } else if ((oldState == ScrimState.AOD // leaving doze
+ && (!mDozeParameters.getAlwaysOn() || mState == ScrimState.UNLOCKED))
|| (mState == ScrimState.AOD && !mDozeParameters.getDisplayNeedsBlanking())) {
// Scheduling a frame isn't enough when:
// • Leaving doze and we need to modify scrim color immediately
// • ColorFade will not kick-in and scrim cannot wait for pre-draw.
onPreDraw();
} else {
+ // Schedule a frame
scheduleUpdate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index f0efed3..00acd7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -43,6 +43,7 @@
import com.android.systemui.statusbar.StatusBarWifiView;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.NoCallingIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import java.util.List;
@@ -62,6 +63,10 @@
public void setIcon(String slot, StatusBarIcon icon);
public void setSignalIcon(String slot, WifiIconState state);
public void setMobileIcons(String slot, List<MobileIconState> states);
+ /**
+ * Display the no calling & SMS icons.
+ */
+ void setNoCallingIcons(String slot, List<NoCallingIconState> states);
public void setIconVisibility(String slot, boolean b);
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 2870152..5e8d590 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -35,6 +35,7 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.NoCallingIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -216,6 +217,29 @@
}
}
+ /**
+ * Accept a list of NoCallingIconStates, and show them in the same slot
+ * @param slot StatusBar slot
+ * @param states All of the no Calling & SMS icon states
+ */
+ @Override
+ public void setNoCallingIcons(String slot, List<NoCallingIconState> states) {
+ Slot noCallingSlot = getSlot(slot);
+ int slotIndex = getSlotIndex(slot);
+
+ for (NoCallingIconState state : states) {
+ StatusBarIconHolder holder = noCallingSlot.getHolderForTag(state.subId);
+ if (holder == null) {
+ holder = StatusBarIconHolder.fromNoCallingState(mContext, state);
+ holder.setVisible(state.visible);
+ setIcon(slotIndex, holder);
+ } else {
+ holder.setVisible(state.visible);
+ setIcon(slotIndex, holder);
+ }
+ }
+ }
+
@Override
public void setExternalIcon(String slot) {
int viewIndex = getViewIndex(getSlotIndex(slot), 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index 88d0035..36a0e63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -23,6 +23,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.NoCallingIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
/**
@@ -70,6 +71,18 @@
return holder;
}
+ /**
+ * Creates a new StatusBarIconHolder from a NoCallingIconState.
+ */
+ public static StatusBarIconHolder fromNoCallingState(
+ Context context, NoCallingIconState state) {
+ StatusBarIconHolder holder = new StatusBarIconHolder();
+ holder.mIcon = new StatusBarIcon(UserHandle.SYSTEM, context.getPackageName(),
+ Icon.createWithResource(context, state.resId), 0, 0, null);
+ holder.mTag = state.subId;
+ return holder;
+ }
+
public int getType() {
return mType;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 7eefaf2..d11e864 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -39,12 +39,14 @@
public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallback,
SecurityController.SecurityControllerCallback, Tunable {
private static final String TAG = "StatusBarSignalPolicy";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final String mSlotAirplane;
private final String mSlotMobile;
private final String mSlotWifi;
private final String mSlotEthernet;
private final String mSlotVpn;
+ private final String mSlotNoCalling;
private final Context mContext;
private final StatusBarIconController mIconController;
@@ -61,9 +63,11 @@
// Track as little state as possible, and only for padding purposes
private boolean mIsAirplaneMode = false;
+ private boolean mIsWifiEnabled = false;
private boolean mWifiVisible = false;
private ArrayList<MobileIconState> mMobileStates = new ArrayList<MobileIconState>();
+ private ArrayList<NoCallingIconState> mNoCallingStates = new ArrayList<NoCallingIconState>();
private WifiIconState mWifiIconState = new WifiIconState();
public StatusBarSignalPolicy(Context context, StatusBarIconController iconController) {
@@ -74,6 +78,7 @@
mSlotWifi = mContext.getString(com.android.internal.R.string.status_bar_wifi);
mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet);
mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn);
+ mSlotNoCalling = mContext.getString(com.android.internal.R.string.status_bar_no_calling);
mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
mIconController = iconController;
@@ -139,24 +144,43 @@
public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
boolean activityIn, boolean activityOut, String description, boolean isTransient,
String statusLabel) {
-
+ if (DEBUG) {
+ Log.d(TAG, "setWifiIndicators: "
+ + "enabled = " + enabled + ","
+ + "statusIcon = " + (statusIcon == null ? "" : statusIcon.toString()) + ","
+ + "qsIcon = " + (qsIcon == null ? "" : qsIcon.toString()) + ","
+ + "activityIn = " + activityIn + ","
+ + "activityOut = " + activityOut + ","
+ + "description = " + description + ","
+ + "isTransient = " + isTransient + ","
+ + "statusLabel = " + statusLabel);
+ }
boolean visible = statusIcon.visible && !mHideWifi;
boolean in = activityIn && mActivityEnabled && visible;
boolean out = activityOut && mActivityEnabled && visible;
+ mIsWifiEnabled = enabled;
WifiIconState newState = mWifiIconState.copy();
- newState.visible = visible;
- newState.resId = statusIcon.icon;
- newState.activityIn = in;
- newState.activityOut = out;
+ if (mWifiIconState.noDefaultNetwork && mWifiIconState.noNetworksAvailable
+ && !mIsAirplaneMode) {
+ newState.visible = true;
+ newState.resId = R.drawable.ic_qs_no_internet_unavailable;
+ } else if (mWifiIconState.noValidatedNetwork && !mWifiIconState.noNetworksAvailable
+ && (!mIsAirplaneMode || (mIsAirplaneMode && mIsWifiEnabled))) {
+ newState.visible = true;
+ newState.resId = R.drawable.ic_qs_no_internet_available;
+ } else {
+ newState.visible = visible;
+ newState.resId = statusIcon.icon;
+ newState.activityIn = in;
+ newState.activityOut = out;
+ newState.contentDescription = statusIcon.contentDescription;
+ MobileIconState first = getFirstMobileState();
+ newState.signalSpacerVisible = first != null && first.typeId != 0;
+ }
newState.slot = mSlotWifi;
newState.airplaneSpacerVisible = mIsAirplaneMode;
- newState.contentDescription = statusIcon.contentDescription;
-
- MobileIconState first = getFirstMobileState();
- newState.signalSpacerVisible = first != null && first.typeId != 0;
-
updateWifiIconWithState(newState);
mWifiIconState = newState;
}
@@ -167,6 +191,7 @@
}
private void updateWifiIconWithState(WifiIconState state) {
+ if (DEBUG) Log.d(TAG, "WifiIconState: " + state == null ? "" : state.toString());
if (state.visible && state.resId > 0) {
mIconController.setSignalIcon(mSlotWifi, state);
mIconController.setIconVisibility(mSlotWifi, true);
@@ -176,11 +201,42 @@
}
@Override
+ public void setNoCallingStatus(boolean noCalling, int subId) {
+ if (DEBUG) {
+ Log.d(TAG, "setNoCallingStatus: "
+ + "noCalling = " + noCalling + ","
+ + "subId = " + subId);
+ }
+ NoCallingIconState state = getNoCallingState(subId);
+ if (state == null) {
+ return;
+ }
+ state.visible = noCalling;
+ mIconController.setNoCallingIcons(
+ mSlotNoCalling, NoCallingIconState.copyStates(mNoCallingStates));
+ }
+
+ @Override
public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
int qsType, boolean activityIn, boolean activityOut,
CharSequence typeContentDescription,
CharSequence typeContentDescriptionHtml, CharSequence description,
boolean isWide, int subId, boolean roaming) {
+ if (DEBUG) {
+ Log.d(TAG, "setMobileDataIndicators: "
+ + "statusIcon = " + (statusIcon == null ? "" : statusIcon.toString()) + ","
+ + "qsIcon = " + (qsIcon == null ? "" : qsIcon.toString()) + ","
+ + "statusType = " + statusType + ","
+ + "qsType = " + qsType + ","
+ + "activityIn = " + activityIn + ","
+ + "activityOut = " + activityOut + ","
+ + "typeContentDescription = " + typeContentDescription + ","
+ + "typeContentDescriptionHtml = " + typeContentDescriptionHtml + ","
+ + "description = " + description + ","
+ + "isWide = " + isWide + ","
+ + "subId = " + subId + ","
+ + "roaming = " + roaming);
+ }
MobileIconState state = getState(subId);
if (state == null) {
return;
@@ -198,6 +254,10 @@
state.activityIn = activityIn && mActivityEnabled;
state.activityOut = activityOut && mActivityEnabled;
+ if (DEBUG) {
+ Log.d(TAG, "MobileIconStates: "
+ + (mMobileStates == null ? "" : mMobileStates.toString()));
+ }
// Always send a copy to maintain value type semantics
mIconController.setMobileIcons(mSlotMobile, MobileIconState.copyStates(mMobileStates));
@@ -211,6 +271,16 @@
}
}
+ private NoCallingIconState getNoCallingState(int subId) {
+ for (NoCallingIconState state : mNoCallingStates) {
+ if (state.subId == subId) {
+ return state;
+ }
+ }
+ Log.e(TAG, "Unexpected subscription " + subId);
+ return null;
+ }
+
private MobileIconState getState(int subId) {
for (MobileIconState state : mMobileStates) {
if (state.subId == subId) {
@@ -237,15 +307,18 @@
*/
@Override
public void setSubs(List<SubscriptionInfo> subs) {
+ if (DEBUG) Log.d(TAG, "setSubs: " + (subs == null ? "" : subs.toString()));
if (hasCorrectSubs(subs)) {
return;
}
mIconController.removeAllIconsForSlot(mSlotMobile);
mMobileStates.clear();
+ mNoCallingStates.clear();
final int n = subs.size();
for (int i = 0; i < n; i++) {
mMobileStates.add(new MobileIconState(subs.get(i).getSubscriptionId()));
+ mNoCallingStates.add(new NoCallingIconState(subs.get(i).getSubscriptionId()));
}
}
@@ -267,6 +340,36 @@
// Noop yay!
}
+ @Override
+ public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
+ boolean noNetworksAvailable) {
+ if (DEBUG) {
+ Log.d(TAG, "setConnectivityStatus: "
+ + "noDefaultNetwork = " + noDefaultNetwork + ","
+ + "noValidatedNetwork = " + noValidatedNetwork + ","
+ + "noNetworksAvailable = " + noNetworksAvailable);
+ }
+ WifiIconState newState = mWifiIconState.copy();
+ newState.noDefaultNetwork = noDefaultNetwork;
+ newState.noValidatedNetwork = noValidatedNetwork;
+ newState.noNetworksAvailable = noNetworksAvailable;
+ newState.slot = mSlotWifi;
+ newState.airplaneSpacerVisible = mIsAirplaneMode;
+ if (noDefaultNetwork && noNetworksAvailable && !mIsAirplaneMode) {
+ newState.visible = true;
+ newState.resId = R.drawable.ic_qs_no_internet_unavailable;
+ } else if (noValidatedNetwork && !noNetworksAvailable
+ && (!mIsAirplaneMode || (mIsAirplaneMode && mIsWifiEnabled))) {
+ newState.visible = true;
+ newState.resId = R.drawable.ic_qs_no_internet_available;
+ } else {
+ newState.visible = false;
+ newState.resId = 0;
+ }
+ updateWifiIconWithState(newState);
+ mWifiIconState = newState;
+ }
+
@Override
public void setEthernetIndicators(IconState state) {
@@ -284,6 +387,10 @@
@Override
public void setIsAirplaneMode(IconState icon) {
+ if (DEBUG) {
+ Log.d(TAG, "setIsAirplaneMode: "
+ + "icon = " + (icon == null ? "" : icon.toString()));
+ }
mIsAirplaneMode = icon.visible && !mHideAirplane;
int resId = icon.icon;
String description = icon.contentDescription;
@@ -301,6 +408,53 @@
// Don't care.
}
+ /**
+ * Stores the StatusBar state for no Calling & SMS.
+ */
+ public static class NoCallingIconState {
+ public boolean visible;
+ public int resId;
+ public int subId;
+
+ private NoCallingIconState(int subId) {
+ this.subId = subId;
+ this.resId = R.drawable.ic_qs_no_calling_sms;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ // Skipping reference equality bc this should be more of a value type
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ NoCallingIconState that = (NoCallingIconState) o;
+ return visible == that.visible
+ && resId == that.resId
+ && subId == that.subId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(visible, resId, subId);
+ }
+
+ private void copyTo(NoCallingIconState other) {
+ other.visible = visible;
+ other.resId = resId;
+ other.subId = subId;
+ }
+
+ private static List<NoCallingIconState> copyStates(List<NoCallingIconState> inStates) {
+ ArrayList<NoCallingIconState> outStates = new ArrayList<>();
+ for (NoCallingIconState state : inStates) {
+ NoCallingIconState copy = new NoCallingIconState(state.subId);
+ state.copyTo(copy);
+ outStates.add(copy);
+ }
+ return outStates;
+ }
+ }
+
private static abstract class SignalIconState {
public boolean visible;
public boolean activityOut;
@@ -340,6 +494,9 @@
public int resId;
public boolean airplaneSpacerVisible;
public boolean signalSpacerVisible;
+ public boolean noDefaultNetwork;
+ public boolean noValidatedNetwork;
+ public boolean noNetworksAvailable;
@Override
public boolean equals(Object o) {
@@ -351,9 +508,12 @@
return false;
}
WifiIconState that = (WifiIconState) o;
- return resId == that.resId &&
- airplaneSpacerVisible == that.airplaneSpacerVisible &&
- signalSpacerVisible == that.signalSpacerVisible;
+ return resId == that.resId
+ && airplaneSpacerVisible == that.airplaneSpacerVisible
+ && signalSpacerVisible == that.signalSpacerVisible
+ && noDefaultNetwork == that.noDefaultNetwork
+ && noValidatedNetwork == that.noValidatedNetwork
+ && noNetworksAvailable == that.noNetworksAvailable;
}
public void copyTo(WifiIconState other) {
@@ -361,6 +521,9 @@
other.resId = resId;
other.airplaneSpacerVisible = airplaneSpacerVisible;
other.signalSpacerVisible = signalSpacerVisible;
+ other.noDefaultNetwork = noDefaultNetwork;
+ other.noValidatedNetwork = noValidatedNetwork;
+ other.noNetworksAvailable = noNetworksAvailable;
}
public WifiIconState copy() {
@@ -372,7 +535,8 @@
@Override
public int hashCode() {
return Objects.hash(super.hashCode(),
- resId, airplaneSpacerVisible, signalSpacerVisible);
+ resId, airplaneSpacerVisible, signalSpacerVisible, noDefaultNetwork,
+ noValidatedNetwork, noNetworksAvailable);
}
@Override public String toString() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index 97d348b..5e88cd5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -135,6 +135,26 @@
}
@Override
+ public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
+ boolean noNetworksAvailable) {
+ post(() -> {
+ for (SignalCallback signalCluster : mSignalCallbacks) {
+ signalCluster.setConnectivityStatus(
+ noDefaultNetwork, noValidatedNetwork, noNetworksAvailable);
+ }
+ });
+ }
+
+ @Override
+ public void setNoCallingStatus(boolean noCalling, int subId) {
+ post(() -> {
+ for (SignalCallback signalCluster : mSignalCallbacks) {
+ signalCluster.setNoCallingStatus(noCalling, subId);
+ }
+ });
+ }
+
+ @Override
public void setSubs(List<SubscriptionInfo> subs) {
obtainMessage(MSG_SUBS_CHANGED, subs).sendToTarget();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
new file mode 100644
index 0000000..a76d08a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.hardware.SensorPrivacyManager.IndividualSensor;
+
+public interface IndividualSensorPrivacyController extends
+ CallbackController<IndividualSensorPrivacyController.Callback> {
+ void init();
+
+ boolean isSensorBlocked(@IndividualSensor int sensor);
+
+ void setSensorBlocked(@IndividualSensor int sensor, boolean blocked);
+
+ interface Callback {
+ void onSensorBlockedChanged(@IndividualSensor int sensor, boolean blocked);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
new file mode 100644
index 0000000..231fe08
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.util.ArraySet;
+import android.util.SparseBooleanArray;
+
+import androidx.annotation.NonNull;
+
+import java.util.Set;
+
+public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPrivacyController {
+
+ private static final int[] SENSORS = new int[] {CAMERA, MICROPHONE};
+
+ private final @NonNull SensorPrivacyManager mSensorPrivacyManager;
+ private final SparseBooleanArray mState = new SparseBooleanArray();
+ private final Set<Callback> mCallbacks = new ArraySet<>();
+
+ public IndividualSensorPrivacyControllerImpl(
+ @NonNull SensorPrivacyManager sensorPrivacyManager) {
+ mSensorPrivacyManager = sensorPrivacyManager;
+ }
+
+ @Override
+ public void init() {
+ for (int sensor : SENSORS) {
+ mSensorPrivacyManager.addSensorPrivacyListener(sensor,
+ (enabled) -> onSensorPrivacyChanged(sensor, enabled));
+
+ mState.put(sensor, mSensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor));
+ }
+ }
+
+ @Override
+ public boolean isSensorBlocked(@IndividualSensor int sensor) {
+ return mState.get(sensor, false);
+ }
+
+ @Override
+ public void setSensorBlocked(@IndividualSensor int sensor, boolean blocked) {
+ mSensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, blocked);
+ }
+
+ @Override
+ public void addCallback(@NonNull Callback listener) {
+ mCallbacks.add(listener);
+ }
+
+ @Override
+ public void removeCallback(@NonNull Callback listener) {
+ mCallbacks.remove(listener);
+ }
+
+ private void onSensorPrivacyChanged(@IndividualSensor int sensor, boolean blocked) {
+ mState.put(sensor, blocked);
+
+ for (Callback callback : mCallbacks) {
+ callback.onSensorBlockedChanged(sensor, blocked);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 947b9182..24b8206 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -36,6 +36,7 @@
import android.telephony.TelephonyManager;
import android.text.Html;
import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -66,6 +67,7 @@
private final String mNetworkNameDefault;
private final String mNetworkNameSeparator;
private final ContentObserver mObserver;
+ private final boolean mProviderModel;
// Save entire info for logging, we only use the id.
final SubscriptionInfo mSubscriptionInfo;
// @VisibleForDemoMode
@@ -140,6 +142,8 @@
};
mMobileStatusTracker = new MobileStatusTracker(mPhone, receiverLooper,
info, mDefaults, mCallback);
+ mProviderModel = FeatureFlagUtils.isEnabled(
+ mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
}
public void setConfiguration(Config config) {
@@ -236,6 +240,11 @@
@Override
public void notifyListeners(SignalCallback callback) {
+ // If the device is on carrier merged WiFi, we should let WifiSignalController to control
+ // the SysUI states.
+ if (mNetworkController.isCarrierMergedWifi(mSubscriptionInfo.getSubscriptionId())) {
+ return;
+ }
MobileIconGroup icons = getIcons();
String contentDescription = getTextIfExists(getContentDescription()).toString();
@@ -253,33 +262,65 @@
|| (mCurrentState.iconGroup == TelephonyIcons.NOT_DEFAULT_DATA))
&& mCurrentState.userSetup;
- // Show icon in QS when we are connected or data is disabled.
- boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
- IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
- getCurrentIconId(), contentDescription);
+ if (mProviderModel) {
+ // Show icon in QS when we are connected or data is disabled.
+ boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
- int qsTypeIcon = 0;
- IconState qsIcon = null;
- CharSequence description = null;
- // Only send data sim callbacks to QS.
- if (mCurrentState.dataSim) {
- qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.qsDataType : 0;
- qsIcon = new IconState(mCurrentState.enabled
- && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
- description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
+ int qsTypeIcon = 0;
+ IconState qsIcon = null;
+ CharSequence description = null;
+ // Only send data sim callbacks to QS.
+ if (mCurrentState.dataSim && mCurrentState.isDefault) {
+ qsTypeIcon =
+ (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.qsDataType : 0;
+ qsIcon = new IconState(mCurrentState.enabled
+ && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
+ description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
+ }
+ boolean activityIn = mCurrentState.dataConnected
+ && !mCurrentState.carrierNetworkChangeMode
+ && mCurrentState.activityIn;
+ boolean activityOut = mCurrentState.dataConnected
+ && !mCurrentState.carrierNetworkChangeMode
+ && mCurrentState.activityOut;
+ showDataIcon &= mCurrentState.dataSim && mCurrentState.isDefault;
+ IconState statusIcon = new IconState(showDataIcon && !mCurrentState.airplaneMode,
+ getCurrentIconId(), contentDescription);
+ int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.dataType : 0;
+ callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+ activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
+ description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
+ mCurrentState.roaming);
+ } else {
+ boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
+ IconState statusIcon = new IconState(
+ mCurrentState.enabled && !mCurrentState.airplaneMode,
+ getCurrentIconId(), contentDescription);
+
+ int qsTypeIcon = 0;
+ IconState qsIcon = null;
+ CharSequence description = null;
+ // Only send data sim callbacks to QS.
+ if (mCurrentState.dataSim) {
+ qsTypeIcon =
+ (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.qsDataType : 0;
+ qsIcon = new IconState(mCurrentState.enabled
+ && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
+ description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
+ }
+ boolean activityIn = mCurrentState.dataConnected
+ && !mCurrentState.carrierNetworkChangeMode
+ && mCurrentState.activityIn;
+ boolean activityOut = mCurrentState.dataConnected
+ && !mCurrentState.carrierNetworkChangeMode
+ && mCurrentState.activityOut;
+ showDataIcon &= mCurrentState.isDefault || dataDisabled;
+ int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.dataType : 0;
+ callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+ activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
+ description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
+ mCurrentState.roaming);
}
- boolean activityIn = mCurrentState.dataConnected
- && !mCurrentState.carrierNetworkChangeMode
- && mCurrentState.activityIn;
- boolean activityOut = mCurrentState.dataConnected
- && !mCurrentState.carrierNetworkChangeMode
- && mCurrentState.activityOut;
- showDataIcon &= mCurrentState.isDefault || dataDisabled;
- int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.dataType : 0;
- callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
- activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
- description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
- mCurrentState.roaming);
}
@Override
@@ -299,6 +340,18 @@
return Utils.isInService(mServiceState);
}
+ String getNonDefaultCarrierName() {
+ if (!mCurrentState.networkNameData.equals(mNetworkNameDefault)) {
+ return mCurrentState.networkNameData;
+ } else if (mSubscriptionInfo.getCarrierName() != null) {
+ return mSubscriptionInfo.getCarrierName().toString();
+ } else if (mSubscriptionInfo.getDisplayName() != null) {
+ return mSubscriptionInfo.getDisplayName().toString();
+ } else {
+ return "";
+ }
+ }
+
private boolean isRoaming() {
// During a carrier change, roaming indications need to be supressed.
if (isCarrierNetworkChangeActive()) {
@@ -405,9 +458,23 @@
mCurrentState.dataSim = mobileStatus.dataSim;
mCurrentState.carrierNetworkChangeMode = mobileStatus.carrierNetworkChangeMode;
mDataState = mobileStatus.dataState;
- mServiceState = mobileStatus.serviceState;
mSignalStrength = mobileStatus.signalStrength;
mTelephonyDisplayInfo = mobileStatus.telephonyDisplayInfo;
+ int lastVoiceState = mServiceState != null ? mServiceState.getState() : -1;
+ mServiceState = mobileStatus.serviceState;
+ int currentVoiceState = mServiceState != null ? mServiceState.getState() : -1;
+ // Only update the no calling Status in the below scenarios
+ // 1. The first valid voice state has been received
+ // 2. The voice state has been changed and either the last or current state is
+ // ServiceState.STATE_IN_SERVICE
+ if (lastVoiceState != currentVoiceState
+ && (lastVoiceState == -1
+ || (lastVoiceState == ServiceState.STATE_IN_SERVICE
+ || currentVoiceState == ServiceState.STATE_IN_SERVICE))) {
+ notifyNoCallingStatusChange(
+ currentVoiceState != ServiceState.STATE_IN_SERVICE,
+ mSubscriptionInfo.getSubscriptionId());
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index b012dc4..f2b0d76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -83,6 +83,22 @@
default void setIsAirplaneMode(IconState icon) {}
default void setMobileDataEnabled(boolean enabled) {}
+
+ /**
+ * Callback for listeners to be able to update the connectivity status
+ * @param noDefaultNetwork whether there is any default network.
+ * @param noValidatedNetwork whether there is any validated network.
+ * @param noNetworksAvailable whether there is any WiFi networks available.
+ */
+ default void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
+ boolean noNetworksAvailable) {}
+
+ /**
+ * Callback for listeners to be able to update the no calling & SMS status
+ * @param noCalling whether the calling and SMS is not working.
+ * @param subId subscription ID for which to update the UI
+ */
+ default void setNoCallingStatus(boolean noCalling, int subId) {}
}
public interface EmergencyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 5f5a83c..92d013e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -34,6 +34,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkScoreManager;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -49,6 +50,7 @@
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import android.util.MathUtils;
import android.util.SparseArray;
@@ -110,6 +112,7 @@
private final BroadcastDispatcher mBroadcastDispatcher;
private final DemoModeController mDemoModeController;
private final Object mLock = new Object();
+ private final boolean mProviderModel;
private Config mConfig;
private PhoneStateListener mPhoneStateListener;
@@ -140,6 +143,8 @@
// States that don't belong to a subcontroller.
private boolean mAirplaneMode = false;
private boolean mHasNoSubs;
+ private boolean mNoDefaultNetwork = false;
+ private boolean mNoNetworksAvailable = true;
private Locale mLocale = null;
// This list holds our ordering.
private List<SubscriptionInfo> mCurrentSubscriptions = new ArrayList<>();
@@ -270,11 +275,39 @@
}
});
+ WifiManager.ScanResultsCallback scanResultsCallback =
+ new WifiManager.ScanResultsCallback() {
+ @Override
+ public void onScanResultsAvailable() {
+ mNoNetworksAvailable = true;
+ for (ScanResult scanResult : mWifiManager.getScanResults()) {
+ if (!scanResult.SSID.equals(mWifiSignalController.getState().ssid)) {
+ mNoNetworksAvailable = false;
+ break;
+ }
+ }
+ // Only update the network availability if there is no default network.
+ if (mNoDefaultNetwork) {
+ mCallbackHandler.setConnectivityStatus(mNoDefaultNetwork, !mInetCondition,
+ mNoNetworksAvailable);
+ }
+ }
+ };
+
+ mWifiManager.registerScanResultsCallback(mReceiverHandler::post, scanResultsCallback);
+
ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback(){
private Network mLastNetwork;
private NetworkCapabilities mLastNetworkCapabilities;
@Override
+ public void onLost(Network network) {
+ mLastNetwork = null;
+ mLastNetworkCapabilities = null;
+ updateConnectivity();
+ }
+
+ @Override
public void onCapabilitiesChanged(
Network network, NetworkCapabilities networkCapabilities) {
boolean lastValidated = (mLastNetworkCapabilities != null) &&
@@ -322,6 +355,8 @@
};
mDemoModeController.addCallback(this);
+ mProviderModel = FeatureFlagUtils.isEnabled(
+ mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
}
private final Runnable mClearForceValidated = () -> {
@@ -441,14 +476,18 @@
private MobileSignalController getDataController() {
int dataSubId = mSubDefaults.getActiveDataSubId();
- if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
+ return getControllerWithSubId(dataSubId);
+ }
+
+ private MobileSignalController getControllerWithSubId(int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
if (DEBUG) Log.e(TAG, "No data sim selected");
return mDefaultSignalController;
}
- if (mMobileSignalControllers.indexOfKey(dataSubId) >= 0) {
- return mMobileSignalControllers.get(dataSubId);
+ if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
+ return mMobileSignalControllers.get(subId);
}
- if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + dataSubId);
+ if (DEBUG) Log.e(TAG, "Cannot find controller for data sub: " + subId);
return mDefaultSignalController;
}
@@ -478,6 +517,15 @@
return dataController.isDataDisabled();
}
+ boolean isCarrierMergedWifi(int subId) {
+ return mWifiSignalController.isCarrierMergedWifi(subId);
+ }
+
+ String getNonDefaultMobileDataNetworkName(int subId) {
+ MobileSignalController controller = getControllerWithSubId(subId);
+ return controller != null ? controller.getNonDefaultCarrierName() : "";
+ }
+
private void notifyControllersMobileDataChanged() {
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
@@ -539,6 +587,9 @@
cb.setIsAirplaneMode(new IconState(mAirplaneMode,
TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
cb.setNoSims(mHasNoSubs, mSimDetected);
+ if (mProviderModel) {
+ cb.setConnectivityStatus(mNoDefaultNetwork, !mInetCondition, mNoNetworksAvailable);
+ }
mWifiSignalController.notifyListeners(cb);
mEthernetSignalController.notifyListeners(cb);
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
@@ -883,6 +934,12 @@
mInetCondition = !mValidatedTransports.isEmpty();
pushConnectivityToSignals();
+ if (mProviderModel) {
+ mNoDefaultNetwork = mConnectedTransports.isEmpty();
+ mCallbackHandler.setConnectivityStatus(mNoDefaultNetwork, !mInetCondition,
+ mNoNetworksAvailable);
+ notifyAllListeners();
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 1d77841..4f4a504 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -33,7 +33,6 @@
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IConnectivityManager;
import android.net.Network;
-import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Handler;
import android.os.RemoteException;
@@ -75,12 +74,8 @@
private static final String TAG = "SecurityController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final NetworkRequest REQUEST = new NetworkRequest.Builder()
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
- .setUids(null)
- .build();
+ private static final NetworkRequest REQUEST =
+ new NetworkRequest.Builder().clearCapabilities().build();
private static final int NO_NETWORK = -1;
private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
index 6d5ce60..4a09234 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyController.java
@@ -23,6 +23,11 @@
CallbackController<SensorPrivacyController.OnSensorPrivacyChangedListener> {
/**
+ * Initialize the controller. Needs to be called after constructing the object
+ */
+ void init();
+
+ /**
* Returns whether sensor privacy is enabled.
*/
boolean isSensorPrivacyEnabled();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
index 20cc46f..a2334f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SensorPrivacyControllerImpl.java
@@ -35,20 +35,21 @@
public class SensorPrivacyControllerImpl implements SensorPrivacyController,
SensorPrivacyManager.OnSensorPrivacyChangedListener {
private SensorPrivacyManager mSensorPrivacyManager;
- private final List<OnSensorPrivacyChangedListener> mListeners;
+ private final List<OnSensorPrivacyChangedListener> mListeners = new ArrayList<>(1);
private Object mLock = new Object();
private boolean mSensorPrivacyEnabled;
/**
* Public constructor.
*/
- @Inject
- public SensorPrivacyControllerImpl(Context context) {
- mSensorPrivacyManager = (SensorPrivacyManager) context.getSystemService(
- Context.SENSOR_PRIVACY_SERVICE);
+ public SensorPrivacyControllerImpl(@NonNull SensorPrivacyManager sensorPrivacyManager) {
+ mSensorPrivacyManager = sensorPrivacyManager;
+ }
+
+ @Override
+ public void init() {
mSensorPrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
mSensorPrivacyManager.addSensorPrivacyListener(this);
- mListeners = new ArrayList<>(1);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index a05fe1f..554145e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -167,6 +167,10 @@
}
}
+ protected final void notifyNoCallingStatusChange(boolean noCalling, int subId) {
+ mCallbackHandler.setNoCallingStatus(noCalling, subId);
+ }
+
/**
* Returns the resource if resId is not 0, and an empty string otherwise.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 4954286..7042e2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -27,6 +27,7 @@
import android.net.wifi.WifiManager;
import android.text.Html;
import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.SignalIcon.IconGroup;
@@ -48,6 +49,7 @@
private final IconGroup mUnmergedWifiIconGroup = WifiIcons.UNMERGED_WIFI;
private final MobileIconGroup mCarrierMergedWifiIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI;
private final WifiManager mWifiManager;
+ private final boolean mProviderModel;
public WifiSignalController(Context context, boolean hasMobileDataFeature,
CallbackHandler callbackHandler, NetworkControllerImpl networkController,
@@ -65,6 +67,8 @@
new WifiTrafficStateCallback());
}
mCurrentState.iconGroup = mLastState.iconGroup = mUnmergedWifiIconGroup;
+ mProviderModel = FeatureFlagUtils.isEnabled(
+ mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
}
@Override
@@ -100,12 +104,26 @@
contentDescription += ("," + mContext.getString(R.string.data_connection_no_internet));
}
IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
- IconState qsIcon = new IconState(mCurrentState.connected,
- mWifiTracker.isCaptivePortal ? R.drawable.ic_qs_wifi_disconnected
- : getQsCurrentIconId(), contentDescription);
- callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
- ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
- wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
+ if (mProviderModel) {
+ IconState qsIcon = null;
+ if (mCurrentState.isDefault) {
+ qsIcon = new IconState(mCurrentState.connected,
+ mWifiTracker.isCaptivePortal ? R.drawable.ic_qs_wifi_disconnected
+ : getQsCurrentIconId(), contentDescription);
+ }
+ callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
+ ssidPresent && mCurrentState.activityIn,
+ ssidPresent && mCurrentState.activityOut,
+ wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
+ } else {
+ IconState qsIcon = new IconState(mCurrentState.connected,
+ mWifiTracker.isCaptivePortal ? R.drawable.ic_qs_wifi_disconnected
+ : getQsCurrentIconId(), contentDescription);
+ callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
+ ssidPresent && mCurrentState.activityIn,
+ ssidPresent && mCurrentState.activityOut,
+ wifiDesc, mCurrentState.isTransient, mCurrentState.statusLabel);
+ }
}
private void notifyListenersForCarrierWifi(SignalCallback callback) {
@@ -127,7 +145,8 @@
int typeIcon = mCurrentState.connected ? icons.dataType : 0;
IconState qsIcon = new IconState(
mCurrentState.connected, getQsCurrentIconIdForCarrierWifi(), contentDescription);
- CharSequence description = mNetworkController.getMobileDataNetworkName();
+ CharSequence description =
+ mNetworkController.getNonDefaultMobileDataNetworkName(mCurrentState.subId);
callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
mCurrentState.activityIn, mCurrentState.activityOut, dataContentDescription,
dataContentDescriptionHtml, description, icons.isWide,
@@ -191,6 +210,11 @@
: mUnmergedWifiIconGroup;
}
+ boolean isCarrierMergedWifi(int subId) {
+ return mCurrentState.isDefault
+ && mCurrentState.isCarrierMerged && (mCurrentState.subId == subId);
+ }
+
@VisibleForTesting
void setActivity(int wifiActivity) {
mCurrentState.activityIn = wifiActivity == DATA_ACTIVITY_INOUT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index 069b405..7a4b912 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -107,11 +107,6 @@
/** */
@Binds
- SensorPrivacyController provideSensorPrivacyControllerImpl(
- SensorPrivacyControllerImpl controllerImpl);
-
- /** */
- @Binds
UserInfoController provideUserInfoContrller(UserInfoControllerImpl controllerImpl);
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index 56a4c203..df889f2 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -20,6 +20,7 @@
import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
import android.content.Context;
+import android.hardware.SensorPrivacyManager;
import android.os.Handler;
import android.os.PowerManager;
@@ -63,6 +64,10 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
+import com.android.systemui.statusbar.policy.IndividualSensorPrivacyControllerImpl;
+import com.android.systemui.statusbar.policy.SensorPrivacyController;
+import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl;
import com.android.systemui.statusbar.tv.notifications.TvNotificationHandler;
import javax.inject.Named;
@@ -109,6 +114,25 @@
return bC;
}
+ @Provides
+ @SysUISingleton
+ static SensorPrivacyController provideSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ SensorPrivacyController spC = new SensorPrivacyControllerImpl(sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
+ @Provides
+ @SysUISingleton
+ static IndividualSensorPrivacyController provideIndividualSensorPrivacyController(
+ SensorPrivacyManager sensorPrivacyManager) {
+ IndividualSensorPrivacyController spC = new IndividualSensorPrivacyControllerImpl(
+ sensorPrivacyManager);
+ spC.init();
+ return spC;
+ }
+
@Binds
@SysUISingleton
abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl);
diff --git a/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt b/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
index ff53a9f..57b3f53 100644
--- a/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
@@ -16,8 +16,8 @@
package com.android.systemui.util
+import android.util.IndentingPrintWriter
import android.view.ViewGroup
-import com.android.internal.util.IndentingPrintWriter
import java.io.PrintWriter
/** [Sequence] that yields all of the direct children of this [ViewGroup] */
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index 08cd6e3..8d77c4a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -33,7 +33,7 @@
static final String REASON_WRAP = "wrap";
/**
- * Default wake-lock timeout, to avoid battery regressions.
+ * Default wake-lock timeout in milliseconds, to avoid battery regressions.
*/
long DEFAULT_MAX_TIMEOUT = 20000;
@@ -104,6 +104,7 @@
if (count == null) {
Log.wtf(TAG, "Releasing WakeLock with invalid reason: " + why,
new Throwable());
+ return;
} else if (count == 1) {
mActiveClients.remove(why);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 844f12e..bf823b4 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -615,12 +615,16 @@
}
/**
- * When a notification is marked Priority, expand the stack if needed,
- * then (maybe create and) select the given bubble.
+ * When a notification is set as important, make it a bubble and expand the stack if
+ * it can bubble.
*
- * @param entry the notification for the bubble to show
+ * @param entry the important notification.
*/
- public void onUserChangedImportance(NotificationEntry entry) {
+ public void onUserSetImportantConversation(NotificationEntry entry) {
+ if (entry.getBubbleMetadata() == null) {
+ // No bubble metadata, nothing to do.
+ return;
+ }
try {
int flags = Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
flags |= Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE;
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index f0ccc6d..f23367b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -16,6 +16,7 @@
package com.android.systemui.wmshell;
+import android.animation.AnimationHandler;
import android.content.Context;
import android.view.IWindowManager;
@@ -28,6 +29,7 @@
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
@@ -58,9 +60,10 @@
DisplayImeController displayImeController, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
TaskStackListenerImpl taskStackListener, Transitions transitions,
- @ShellMainThread ShellExecutor mainExecutor) {
- return new LegacySplitScreenController(context, displayController, systemWindows,
+ @ShellMainThread ShellExecutor mainExecutor,
+ @ChoreographerSfVsync AnimationHandler sfVsyncAnimationHandler) {
+ return LegacySplitScreenController.create(context, displayController, systemWindows,
displayImeController, transactionPool, shellTaskOrganizer, syncQueue,
- taskStackListener, transitions, mainExecutor);
+ taskStackListener, transitions, mainExecutor, sfVsyncAnimationHandler);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index bcb4386..1b5877f 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -19,6 +19,7 @@
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import android.animation.AnimationHandler;
+import android.app.ActivityTaskManager;
import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.LauncherApps;
@@ -70,6 +71,8 @@
import com.android.wm.shell.pip.PipUiEventLogger;
import com.android.wm.shell.pip.phone.PipAppOpsListener;
import com.android.wm.shell.pip.phone.PipTouchHandler;
+import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -145,18 +148,18 @@
}
/**
- * Provide a Shell animation-thread AnimationHandler. The AnimationHandler can be set on
+ * Provide a Shell main-thread AnimationHandler. The AnimationHandler can be set on
* {@link android.animation.ValueAnimator}s and will ensure that the animation will run on
- * the Shell animation-thread.
+ * the Shell main-thread with the SF vsync.
*/
@WMSingleton
@Provides
@ChoreographerSfVsync
- public static AnimationHandler provideShellAnimationExecutorSfVsyncAnimationHandler(
- @ShellAnimationThread ShellExecutor shellAnimationExecutor) {
+ public static AnimationHandler provideShellMainExecutorSfVsyncAnimationHandler(
+ @ShellMainThread ShellExecutor mainExecutor) {
try {
AnimationHandler handler = new AnimationHandler();
- shellAnimationExecutor.executeBlocking(() -> {
+ mainExecutor.executeBlocking(() -> {
// This is called on the animation thread since it calls
// Choreographer.getSfInstance() which returns a thread-local Choreographer instance
// that uses the SF vsync
@@ -174,6 +177,7 @@
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
+ Optional<SplitScreen> splitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
@@ -182,6 +186,7 @@
dragAndDropController,
shellTaskOrganizer,
legacySplitScreenOptional,
+ splitScreenOptional,
appPairsOptional,
fullscreenTaskListener,
transitions,
@@ -197,14 +202,15 @@
static Optional<ShellCommandHandler> provideShellCommandHandler(
ShellTaskOrganizer shellTaskOrganizer,
Optional<LegacySplitScreen> legacySplitScreenOptional,
+ Optional<SplitScreen> splitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
Optional<AppPairs> appPairsOptional,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.of(ShellCommandHandlerImpl.create(shellTaskOrganizer,
- legacySplitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
- appPairsOptional, mainExecutor));
+ legacySplitScreenOptional, splitScreenOptional, pipOptional, oneHandedOptional,
+ hideDisplayCutout, appPairsOptional, mainExecutor));
}
@WMSingleton
@@ -306,6 +312,19 @@
@BindsOptionalOf
abstract LegacySplitScreen optionalLegacySplitScreen();
+ @WMSingleton
+ @Provides
+ static Optional<SplitScreen> provideSplitScreen(ShellTaskOrganizer shellTaskOrganizer,
+ SyncTransactionQueue syncQueue, Context context,
+ RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
+ if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
+ return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
+ rootTaskDisplayAreaOrganizer));
+ } else {
+ return Optional.empty();
+ }
+ }
+
@BindsOptionalOf
abstract AppPairs optionalAppPairs();
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 88f6e1f..8105250 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -16,10 +16,13 @@
package com.android.systemui.wmshell;
+import android.animation.AnimationHandler;
+import android.app.ActivityTaskManager;
import android.content.Context;
import android.view.IWindowManager;
import com.android.systemui.dagger.WMSingleton;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.apppairs.AppPairs;
@@ -32,6 +35,7 @@
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
@@ -46,6 +50,8 @@
import com.android.wm.shell.pip.phone.PipAppOpsListener;
import com.android.wm.shell.pip.phone.PipController;
import com.android.wm.shell.pip.phone.PipTouchHandler;
+import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -75,17 +81,20 @@
DisplayImeController displayImeController, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
TaskStackListenerImpl taskStackListener, Transitions transitions,
- @ShellMainThread ShellExecutor mainExecutor) {
- return new LegacySplitScreenController(context, displayController, systemWindows,
+ @ShellMainThread ShellExecutor mainExecutor,
+ @ChoreographerSfVsync AnimationHandler sfVsyncAnimationHandler) {
+ return LegacySplitScreenController.create(context, displayController, systemWindows,
displayImeController, transactionPool, shellTaskOrganizer, syncQueue,
- taskStackListener, transitions, mainExecutor);
+ taskStackListener, transitions, mainExecutor, sfVsyncAnimationHandler);
}
@WMSingleton
@Provides
static AppPairs provideAppPairs(ShellTaskOrganizer shellTaskOrganizer,
- SyncTransactionQueue syncQueue, DisplayController displayController) {
- return new AppPairsController(shellTaskOrganizer, syncQueue, displayController);
+ SyncTransactionQueue syncQueue, DisplayController displayController,
+ @ShellMainThread ShellExecutor mainExecutor) {
+ return AppPairsController.create(shellTaskOrganizer, syncQueue, displayController,
+ mainExecutor);
}
@WMSingleton
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
index 53bae86..40549d69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
@@ -53,7 +53,7 @@
@Before
public void SysuiSetup() {
- SystemUIFactory.createFromConfig(mContext);
+ SystemUIFactory.createFromConfig(mContext, true);
mDependency = new TestableDependency(
SystemUIFactory.getInstance().getSysUIComponent().createDependency());
Dependency.setInstance(mDependency);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index a65c352..c052563 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -106,6 +106,7 @@
@Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
private IUdfpsOverlayController mOverlayController;
@Captor private ArgumentCaptor<UdfpsView.OnTouchListener> mTouchListenerCaptor;
+ @Captor private ArgumentCaptor<Runnable> mRunAfterShowingScrimAndDotCaptor;
@Before
public void setUp() {
@@ -160,14 +161,16 @@
@Test
public void showUdfpsOverlay_addsViewToWindow() throws RemoteException {
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
+ mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ IUdfpsOverlayController.REASON_AUTH);
mFgExecutor.runAllReady();
verify(mWindowManager).addView(eq(mUdfpsView), any());
}
@Test
public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException {
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
+ mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ IUdfpsOverlayController.REASON_AUTH);
mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
mFgExecutor.runAllReady();
verify(mWindowManager).removeView(eq(mUdfpsView));
@@ -180,38 +183,47 @@
when(mUdfpsView.isValidTouch(anyFloat(), anyFloat(), anyFloat())).thenReturn(true);
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
+ mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ IUdfpsOverlayController.REASON_AUTH);
mFgExecutor.runAllReady();
// WHEN ACTION_DOWN is received
verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0);
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, event);
event.recycle();
- // THEN the event is passed to the FingerprintManager
+ // THEN the scrim and dot is shown
+ verify(mUdfpsView).showScrimAndDot();
+ // AND a runnable that passes the event to FingerprintManager is set on the view
+ verify(mUdfpsView).setRunAfterShowingScrimAndDot(
+ mRunAfterShowingScrimAndDotCaptor.capture());
+ mRunAfterShowingScrimAndDotCaptor.getValue().run();
verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
eq(0), eq(0f), eq(0f));
- // AND the scrim and dot is shown
- verify(mUdfpsView).showScrimAndDot();
}
@Test
public void aodInterrupt() throws RemoteException {
// GIVEN that the overlay is showing
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
+ mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ IUdfpsOverlayController.REASON_AUTH);
mFgExecutor.runAllReady();
// WHEN fingerprint is requested because of AOD interrupt
mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
- // THEN the event is passed to the FingerprintManager
+ // THEN the scrim and dot is shown
+ verify(mUdfpsView).showScrimAndDot();
+ // AND a runnable that passes the event to FingerprintManager is set on the view
+ verify(mUdfpsView).setRunAfterShowingScrimAndDot(
+ mRunAfterShowingScrimAndDotCaptor.capture());
+ mRunAfterShowingScrimAndDotCaptor.getValue().run();
verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
eq(0), eq(3f) /* minor */, eq(2f) /* major */);
- // AND the scrim and dot is shown
- verify(mUdfpsView).showScrimAndDot();
}
@Test
public void cancelAodInterrupt() throws RemoteException {
// GIVEN AOD interrupt
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
+ mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ IUdfpsOverlayController.REASON_AUTH);
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it is cancelled
@@ -223,7 +235,8 @@
@Test
public void aodInterruptTimeout() throws RemoteException {
// GIVEN AOD interrupt
- mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
+ mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
+ IUdfpsOverlayController.REASON_AUTH);
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it times out
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 96f46eaa..e761da4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -59,8 +59,8 @@
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.pip.Pip;
import org.junit.After;
import org.junit.Before;
@@ -106,6 +106,7 @@
mock(SystemActions.class),
Dependency.get(Dependency.MAIN_HANDLER),
mock(UiEventLogger.class),
+ mock(NavigationBarOverlayController.class),
mock(ConfigurationController.class)));
initializeNavigationBars();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 851d486..2b76f1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -76,8 +76,8 @@
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.utils.leaks.LeakCheckedTest;
-import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.pip.Pip;
import org.junit.Before;
import org.junit.Rule;
@@ -232,6 +232,7 @@
mock(NotificationRemoteInputManager.class),
mock(SystemActions.class),
mHandler,
+ mock(NavigationBarOverlayController.class),
mUiEventLogger));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
index e6cc107..64b9676 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -21,6 +21,8 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
@@ -30,13 +32,19 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.INotificationManager;
import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.app.Person;
+import android.app.people.ConversationChannel;
+import android.app.people.IPeopleManager;
import android.appwidget.AppWidgetManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
import android.database.Cursor;
import android.graphics.drawable.Icon;
@@ -45,6 +53,7 @@
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.Settings;
+import android.service.notification.ConversationChannelWrapper;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
@@ -62,7 +71,10 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Arrays;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -103,6 +115,12 @@
@Mock
private NotificationListener mListenerService;
@Mock
+ private INotificationManager mNotificationManager;
+ @Mock
+ private IPeopleManager mPeopleManager;
+ @Mock
+ private LauncherApps mLauncherApps;
+ @Mock
private IAppWidgetService mIAppWidgetService;
@Mock
private AppWidgetManager mAppWidgetManager;
@@ -137,6 +155,85 @@
}
@Test
+ public void testGetTilesReturnsSortedListWithMultipleRecentConversations() throws Exception {
+ // Ensure the less-recent Important conversation is before more recent conversations.
+ ConversationChannelWrapper newerNonImportantConversation = getConversationChannelWrapper(
+ SHORTCUT_ID, false, 3);
+ ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper(
+ SHORTCUT_ID + 1,
+ true, 1);
+ when(mNotificationManager.getConversations(anyBoolean())).thenReturn(
+ new ParceledListSlice(Arrays.asList(
+ newerNonImportantConversation, olderImportantConversation)));
+
+ // Ensure the non-Important conversation is sorted between these recent conversations.
+ ConversationChannel recentConversationBeforeNonImportantConversation =
+ getConversationChannel(
+ SHORTCUT_ID + 2, 4);
+ ConversationChannel recentConversationAfterNonImportantConversation =
+ getConversationChannel(SHORTCUT_ID + 3,
+ 2);
+ when(mPeopleManager.getRecentConversations()).thenReturn(
+ new ParceledListSlice(Arrays.asList(recentConversationAfterNonImportantConversation,
+ recentConversationBeforeNonImportantConversation)));
+
+ List<String> orderedShortcutIds = PeopleSpaceUtils.getTiles(
+ mContext, mNotificationManager, mPeopleManager,
+ mLauncherApps).stream().map(tile -> tile.getId()).collect(Collectors.toList());
+
+ assertThat(orderedShortcutIds).containsExactly(
+ // Even though the oldest conversation, should be first since "important"
+ olderImportantConversation.getShortcutInfo().getId(),
+ // Non-priority conversations should be sorted within recent conversations.
+ recentConversationBeforeNonImportantConversation.getShortcutInfo().getId(),
+ newerNonImportantConversation.getShortcutInfo().getId(),
+ recentConversationAfterNonImportantConversation.getShortcutInfo().getId())
+ .inOrder();
+ }
+
+ @Test
+ public void testGetTilesReturnsSortedListWithMultipleImportantAndRecentConversations()
+ throws Exception {
+ // Ensure the less-recent Important conversation is before more recent conversations.
+ ConversationChannelWrapper newerNonImportantConversation = getConversationChannelWrapper(
+ SHORTCUT_ID, false, 3);
+ ConversationChannelWrapper newerImportantConversation = getConversationChannelWrapper(
+ SHORTCUT_ID + 1, true, 3);
+ ConversationChannelWrapper olderImportantConversation = getConversationChannelWrapper(
+ SHORTCUT_ID + 2,
+ true, 1);
+ when(mNotificationManager.getConversations(anyBoolean())).thenReturn(
+ new ParceledListSlice(Arrays.asList(
+ newerNonImportantConversation, newerImportantConversation,
+ olderImportantConversation)));
+
+ // Ensure the non-Important conversation is sorted between these recent conversations.
+ ConversationChannel recentConversationBeforeNonImportantConversation =
+ getConversationChannel(
+ SHORTCUT_ID + 3, 4);
+ ConversationChannel recentConversationAfterNonImportantConversation =
+ getConversationChannel(SHORTCUT_ID + 4,
+ 2);
+ when(mPeopleManager.getRecentConversations()).thenReturn(
+ new ParceledListSlice(Arrays.asList(recentConversationAfterNonImportantConversation,
+ recentConversationBeforeNonImportantConversation)));
+
+ List<String> orderedShortcutIds = PeopleSpaceUtils.getTiles(
+ mContext, mNotificationManager, mPeopleManager,
+ mLauncherApps).stream().map(tile -> tile.getId()).collect(Collectors.toList());
+
+ assertThat(orderedShortcutIds).containsExactly(
+ // Important conversations should be sorted at the beginning.
+ newerImportantConversation.getShortcutInfo().getId(),
+ olderImportantConversation.getShortcutInfo().getId(),
+ // Non-priority conversations should be sorted within recent conversations.
+ recentConversationBeforeNonImportantConversation.getShortcutInfo().getId(),
+ newerNonImportantConversation.getShortcutInfo().getId(),
+ recentConversationAfterNonImportantConversation.getShortcutInfo().getId())
+ .inOrder();
+ }
+
+ @Test
public void testGetLastMessagingStyleMessageNoMessage() {
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
@@ -385,4 +482,30 @@
verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
any());
}
-}
+
+ private ConversationChannelWrapper getConversationChannelWrapper(String shortcutId,
+ boolean importantConversation, long lastInteractionTimestamp) throws Exception {
+ ConversationChannelWrapper convo = new ConversationChannelWrapper();
+ NotificationChannel notificationChannel = new NotificationChannel(shortcutId,
+ "channel" + shortcutId,
+ NotificationManager.IMPORTANCE_DEFAULT);
+ notificationChannel.setImportantConversation(importantConversation);
+ convo.setNotificationChannel(notificationChannel);
+ convo.setShortcutInfo(new ShortcutInfo.Builder(mContext, shortcutId).setLongLabel(
+ "name").build());
+ when(mPeopleManager.getLastInteraction(anyString(), anyInt(),
+ eq(shortcutId))).thenReturn(lastInteractionTimestamp);
+ return convo;
+ }
+
+ private ConversationChannel getConversationChannel(String shortcutId,
+ long lastInteractionTimestamp) throws Exception {
+ ShortcutInfo shortcutInfo = new ShortcutInfo.Builder(mContext, shortcutId).setLongLabel(
+ "name").build();
+ ConversationChannel convo = new ConversationChannel(shortcutInfo, 0, null, null,
+ lastInteractionTimestamp, false);
+ when(mPeopleManager.getLastInteraction(anyString(), anyInt(),
+ eq(shortcutId))).thenReturn(lastInteractionTimestamp);
+ return convo;
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index 63ea7dd6..e7363f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -207,7 +207,7 @@
throws RemoteException {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
- when(mINotificationManager.getConversations(true)).thenReturn(
+ when(mINotificationManager.getConversations(false)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
@@ -229,7 +229,7 @@
throws RemoteException {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
- when(mINotificationManager.getConversations(true)).thenReturn(
+ when(mINotificationManager.getConversations(false)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
@@ -326,7 +326,7 @@
public void testDoNotUpdateNotificationPostedIfNoExistingTile() throws RemoteException {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
- when(mINotificationManager.getConversations(true)).thenReturn(
+ when(mINotificationManager.getConversations(false)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
@@ -346,7 +346,7 @@
public void testDoNotUpdateNotificationRemovedIfNoExistingTile() throws RemoteException {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
- when(mINotificationManager.getConversations(true)).thenReturn(
+ when(mINotificationManager.getConversations(false)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
@@ -368,7 +368,7 @@
public void testUpdateNotificationPostedIfExistingTile() throws RemoteException {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
- when(mINotificationManager.getConversations(true)).thenReturn(
+ when(mINotificationManager.getConversations(false)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
@@ -389,7 +389,7 @@
throws RemoteException {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
- when(mINotificationManager.getConversations(true)).thenReturn(
+ when(mINotificationManager.getConversations(false)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
@@ -416,7 +416,7 @@
public void testUpdateNotificationRemovedIfExistingTile() throws RemoteException {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0);
- when(mINotificationManager.getConversations(true)).thenReturn(
+ when(mINotificationManager.getConversations(false)).thenReturn(
new ParceledListSlice(getConversationWithShortcutId()));
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index d452861..aa7143e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -40,6 +40,7 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -84,7 +85,6 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.wm.shell.animation.FlingAnimationUtils;
import org.junit.Before;
@@ -139,7 +139,7 @@
@Mock
private NotificationPanelView mView;
@Mock
- private InjectionInflationController mInjectionInflationController;
+ private LayoutInflater mLayoutInflater;
@Mock
private DynamicPrivacyController mDynamicPrivacyController;
@Mock
@@ -264,7 +264,7 @@
.thenReturn(mKeyguardStatusViewController);
mNotificationPanelViewController = new NotificationPanelViewController(mView,
mResources,
- mInjectionInflationController,
+ mLayoutInflater,
coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
new FalsingManagerFake(), new FalsingCollectorFake(), mShadeController,
mNotificationLockscreenUserManager, mNotificationEntryManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 8f5d308..273a77b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -25,7 +25,6 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.atLeastOnce;
@@ -58,6 +57,7 @@
import android.telephony.TelephonyManager;
import android.testing.TestableLooper;
import android.testing.TestableResources;
+import android.util.FeatureFlagUtils;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -75,6 +75,7 @@
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestWatcher;
@@ -121,7 +122,8 @@
protected int mSubId;
private NetworkCapabilities mNetCapabilities;
- private ConnectivityManager.NetworkCallback mDefaultNetworkCallback;
+ private ConnectivityManager.NetworkCallback mDefaultCallbackInWifiTracker;
+ private ConnectivityManager.NetworkCallback mDefaultCallbackInNetworkController;
private ConnectivityManager.NetworkCallback mNetworkCallback;
@Rule
@@ -143,6 +145,7 @@
@Before
public void setUp() throws Exception {
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL, true);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
Settings.Global.putInt(mContext.getContentResolver(), Global.AIRPLANE_MODE_ON, 0);
TestableResources res = mContext.getOrCreateTestableResources();
@@ -222,6 +225,11 @@
mNetworkController.addEmergencyListener(null);
}
+ @After
+ public void tearDown() throws Exception {
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL, false);
+ }
+
protected void setupNetworkController() {
// For now just pretend to be the data sim, so we can test that too.
mSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
@@ -235,8 +243,10 @@
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
verify(mMockCm, atLeastOnce())
.registerDefaultNetworkCallback(callbackArg.capture(), isA(Handler.class));
- mDefaultNetworkCallback = callbackArg.getValue();
- assertNotNull(mDefaultNetworkCallback);
+ mDefaultCallbackInWifiTracker = callbackArg.getAllValues().get(0);
+ mDefaultCallbackInNetworkController = callbackArg.getAllValues().get(1);
+ assertNotNull(mDefaultCallbackInWifiTracker);
+ assertNotNull(mDefaultCallbackInNetworkController);
verify(mMockCm, atLeastOnce()).registerNetworkCallback(
isA(NetworkRequest.class), callbackArg.capture(), isA(Handler.class));
mNetworkCallback = callbackArg.getValue();
@@ -294,12 +304,22 @@
mNetworkController.onReceive(mContext, i);
}
- public void setConnectivityViaCallback(
+ public void setConnectivityViaCallbackInNetworkController(
int networkType, boolean validated, boolean isConnected, WifiInfo wifiInfo) {
- mNetCapabilities.setTransportInfo(wifiInfo);
+ if (networkType == NetworkCapabilities.TRANSPORT_WIFI) {
+ mNetCapabilities.setTransportInfo(wifiInfo);
+ }
setConnectivityCommon(networkType, validated, isConnected);
- mDefaultNetworkCallback.onCapabilitiesChanged(
- mock(Network.class), new NetworkCapabilities(mNetCapabilities));
+ mDefaultCallbackInNetworkController.onCapabilitiesChanged(
+ mock(Network.class), new NetworkCapabilities(mNetCapabilities));
+ }
+
+ public void setConnectivityViaCallbackInWifiTracker(
+ int networkType, boolean validated, boolean isConnected, WifiInfo wifiInfo) {
+ if (networkType == NetworkCapabilities.TRANSPORT_WIFI) {
+ mNetCapabilities.setTransportInfo(wifiInfo);
+ }
+ setConnectivityCommon(networkType, validated, isConnected);
if (networkType == NetworkCapabilities.TRANSPORT_WIFI) {
if (isConnected) {
mNetworkCallback.onCapabilitiesChanged(
@@ -310,6 +330,16 @@
}
}
+ public void setConnectivityViaDefaultCallbackInWifiTracker(
+ int networkType, boolean validated, boolean isConnected, WifiInfo wifiInfo) {
+ if (networkType == NetworkCapabilities.TRANSPORT_WIFI) {
+ mNetCapabilities.setTransportInfo(wifiInfo);
+ }
+ setConnectivityCommon(networkType, validated, isConnected);
+ mDefaultCallbackInWifiTracker.onCapabilitiesChanged(
+ mock(Network.class), new NetworkCapabilities(mNetCapabilities));
+ }
+
private void setConnectivityCommon(
int networkType, boolean validated, boolean isConnected){
// TODO: Separate out into several NetworkCapabilities.
@@ -457,10 +487,9 @@
any(),
typeIconArg.capture(),
anyInt(), anyBoolean(), anyBoolean(),
- any(CharSequence.class), any(CharSequence.class), any(CharSequence.class),
+ any(CharSequence.class), any(CharSequence.class), any(),
anyBoolean(), anyInt(), eq(roaming));
IconState iconState = iconArg.getValue();
-
int state = icon == -1 ? 0
: SignalDrawable.getState(icon, CellSignalStrength.getNumSignalStrengthLevels(),
!inet);
@@ -507,7 +536,7 @@
dataOutArg.capture(),
typeContentDescriptionArg.capture(),
typeContentDescriptionHtmlArg.capture(),
- anyString(), anyBoolean(), anyInt(), anyBoolean());
+ any(), anyBoolean(), anyInt(), anyBoolean());
IconState iconState = iconArg.getValue();
@@ -522,8 +551,12 @@
assertEquals("Visibility in status bar", visible, iconState.visible);
iconState = qsIconArg.getValue();
- assertEquals("Visibility in quick settings", qsVisible, iconState.visible);
- assertEquals("Signal icon in quick settings", state, iconState.icon);
+ if (visible) {
+ assertEquals("Visibility in quick settings", qsVisible, iconState.visible);
+ assertEquals("Signal icon in quick settings", state, iconState.icon);
+ } else {
+ assertEquals("Cellular is not default", null, iconState);
+ }
assertEquals("Data icon in quick settings", qsTypeIcon, (int) qsTypeIconArg.getValue());
assertEquals("Data direction in in quick settings", dataIn,
(boolean) dataInArg.getValue());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index d11aee8..37b6a5d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -129,7 +129,7 @@
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
// Verify that a SignalDrawable with a cut out is used to display data disabled.
- verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
+ verifyLastMobileDataIndicators(false, DEFAULT_SIGNAL_STRENGTH, 0,
true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
false, true, NO_DATA_STRING, NO_DATA_STRING);
}
@@ -143,7 +143,7 @@
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
// Verify that a SignalDrawable with a cut out is used to display data disabled.
- verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
+ verifyLastMobileDataIndicators(false, DEFAULT_SIGNAL_STRENGTH, 0,
true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
false, true, NO_DATA_STRING, NO_DATA_STRING);
}
@@ -158,7 +158,7 @@
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
// Verify that a SignalDrawable with a cut out is used to display data disabled.
- verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
+ verifyLastMobileDataIndicators(false, DEFAULT_SIGNAL_STRENGTH, 0,
true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
false, false, NOT_DEFAULT_DATA_STRING, NOT_DEFAULT_DATA_STRING);
}
@@ -173,7 +173,7 @@
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
// Verify that a SignalDrawable with a cut out is used to display data disabled.
- verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, 0,
+ verifyLastMobileDataIndicators(false, DEFAULT_SIGNAL_STRENGTH, 0,
true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false,
false, false, NOT_DEFAULT_DATA_STRING, NOT_DEFAULT_DATA_STRING);
}
@@ -190,7 +190,8 @@
TestableLooper.get(this).processAllMessages();
// Don't show the X until the device is setup.
- verifyDataIndicators(0);
+ verifyLastMobileDataIndicators(false, DEFAULT_SIGNAL_STRENGTH, 0,
+ true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false, false);
}
@Test
@@ -205,7 +206,9 @@
mConfig.alwaysShowDataRatIcon = true;
mNetworkController.handleConfigurationChanged();
- verifyDataIndicators(TelephonyIcons.ICON_G);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
+ verifyLastMobileDataIndicators(false, DEFAULT_SIGNAL_STRENGTH, TelephonyIcons.ICON_G,
+ true, DEFAULT_QS_SIGNAL_STRENGTH, 0, false, false);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index da35de9..c0d9c3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -262,7 +262,7 @@
setConnectivityViaBroadcast(mMobileSignalController.mTransportType, false, false);
setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
- verifyLastMobileDataIndicators(true, DEFAULT_LEVEL, 0);
+ verifyLastMobileDataIndicators(false, DEFAULT_LEVEL, 0);
}
// Some tests of actual NetworkController code, just internals not display stuff
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 9c9d6ea..44c5edb 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
@@ -20,6 +20,7 @@
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -34,6 +35,12 @@
private static final int MAX_RSSI = -55;
private WifiInfo mWifiInfo = mock(WifiInfo.class);
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ when(mWifiInfo.makeCopy(anyBoolean())).thenReturn(mWifiInfo);
+ }
+
@Test
public void testWifiIcon() {
String testSsid = "Test SSID";
@@ -42,16 +49,16 @@
setWifiState(true, testSsid);
setWifiLevel(0);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
+
// Connected, but still not validated - does not show
verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
setWifiLevel(testLevel);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, false, true);
// Icon does not show if not validated
verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
}
@@ -70,11 +77,12 @@
setWifiState(true, testSsid);
for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
setWifiLevel(testLevel);
-
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+ setConnectivityViaDefaultCallbackInWifiTracker(
+ NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
verifyLastQsWifiIcon(true, true, WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][testLevel],
testSsid);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, false, true);
verifyLastQsWifiIcon(true, true, WifiIcons.QS_WIFI_SIGNAL_STRENGTH[0][testLevel],
testSsid);
}
@@ -88,7 +96,9 @@
setWifiEnabled(true);
setWifiState(true, testSsid);
setWifiLevel(testLevel);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+ setConnectivityViaDefaultCallbackInWifiTracker(
+ NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
verifyLastQsWifiIcon(true, true,
WifiIcons.QS_WIFI_SIGNAL_STRENGTH[1][testLevel], testSsid);
@@ -113,17 +123,15 @@
setWifiEnabled(true);
setWifiState(true, testSsid);
setWifiLevel(testLevel);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
setupDefaultSignal();
setGsmRoaming(true);
// Still be on wifi though.
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_CELLULAR, false, false, mWifiInfo);
- verifyLastMobileDataIndicators(true,
- DEFAULT_LEVEL,
- 0, true);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
+ verifyLastMobileDataIndicators(false, DEFAULT_LEVEL, 0, true);
}
@Test
@@ -134,10 +142,11 @@
setWifiEnabled(true);
setWifiState(true, testSsid);
setWifiLevel(testLevel);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
+ setConnectivityViaCallbackInNetworkController(
+ NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
verifyLastWifiIcon(false, WifiIcons.WIFI_SIGNAL_STRENGTH[0][testLevel]);
}
@@ -149,11 +158,12 @@
setWifiEnabled(true);
setWifiState(true, testSsid);
setWifiLevel(testLevel);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
+ setConnectivityViaBroadcast(NetworkCapabilities.TRANSPORT_WIFI, true, true);
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
setWifiState(false, testSsid);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, false, false, mWifiInfo);
+ setConnectivityViaCallbackInNetworkController(
+ NetworkCapabilities.TRANSPORT_WIFI, false, false, mWifiInfo);
verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
}
@@ -164,14 +174,17 @@
setWifiEnabled(true);
verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_VPN, false, true, mWifiInfo);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_VPN, true, true, mWifiInfo);
+ setConnectivityViaCallbackInNetworkController(
+ NetworkCapabilities.TRANSPORT_VPN, false, true, mWifiInfo);
+ setConnectivityViaCallbackInNetworkController(
+ NetworkCapabilities.TRANSPORT_VPN, true, true, mWifiInfo);
verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
// Mock calling setUnderlyingNetworks.
setWifiState(true, testSsid);
setWifiLevel(testLevel);
- setConnectivityViaCallback(NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
+ setConnectivityViaCallbackInNetworkController(
+ NetworkCapabilities.TRANSPORT_WIFI, true, true, mWifiInfo);
verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[1][testLevel]);
}
@@ -212,9 +225,8 @@
// Put RSSI in the middle of the range.
rssi += amountPerLevel / 2;
when(mWifiInfo.getRssi()).thenReturn(rssi);
- Intent i = new Intent(WifiManager.RSSI_CHANGED_ACTION);
- i.putExtra(WifiManager.EXTRA_NEW_RSSI, rssi);
- mNetworkController.onReceive(mContext, i);
+ setConnectivityViaCallbackInWifiTracker(
+ NetworkCapabilities.TRANSPORT_WIFI, false, true, mWifiInfo);
}
protected void setWifiEnabled(boolean enabled) {
@@ -224,14 +236,9 @@
}
protected void setWifiState(boolean connected, String ssid) {
- Intent i = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- NetworkInfo networkInfo = mock(NetworkInfo.class);
- when(networkInfo.isConnected()).thenReturn(connected);
when(mWifiInfo.getSSID()).thenReturn(ssid);
- when(mMockWm.getConnectionInfo()).thenReturn(mWifiInfo);
-
- i.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
- mNetworkController.onReceive(mContext, i);
+ setConnectivityViaCallbackInWifiTracker(
+ NetworkCapabilities.TRANSPORT_WIFI, false, connected, mWifiInfo);
}
protected void verifyLastQsDataDirection(boolean in, boolean out) {
@@ -256,9 +263,13 @@
anyBoolean(), descArg.capture(), anyBoolean(), any());
IconState iconState = iconArg.getValue();
assertEquals("WiFi enabled, in quick settings", enabled, (boolean) enabledArg.getValue());
- assertEquals("WiFi connected, in quick settings", connected, iconState.visible);
- assertEquals("WiFi signal, in quick settings", icon, iconState.icon);
assertEquals("WiFI desc (ssid), in quick settings", description, descArg.getValue());
+ if (enabled && connected) {
+ assertEquals("WiFi connected, in quick settings", connected, iconState.visible);
+ assertEquals("WiFi signal, in quick settings", icon, iconState.icon);
+ } else {
+ assertEquals("WiFi is not default", null, iconState);
+ }
}
protected void verifyLastWifiIcon(boolean visible, int icon) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index 2e874a6..c0af15b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -20,6 +20,7 @@
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.NoCallingIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import java.util.List;
@@ -65,6 +66,10 @@
}
@Override
+ public void setNoCallingIcons(String slot, List<NoCallingIconState> states) {
+ }
+
+ @Override
public void setIconVisibility(String slotTty, boolean b) {
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 446d3f2..8b86403 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -120,4 +120,4 @@
verify(mConfigurationController).addCallback(
any(ConfigurationController.ConfigurationListener.class));
}
-}
\ No newline at end of file
+}
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_apps.xml
index 228e2cc..95c0867 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_apps.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_apps.xml
@@ -20,30 +20,30 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 6 4 C 7.10456949966 4 8 4.89543050034 8 6 C 8 7.10456949966 7.10456949966 8 6 8 C 4.89543050034 8 4 7.10456949966 4 6 C 4 4.89543050034 4.89543050034 4 6 4 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 4 C 13.1045694997 4 14 4.89543050034 14 6 C 14 7.10456949966 13.1045694997 8 12 8 C 10.8954305003 8 10 7.10456949966 10 6 C 10 4.89543050034 10.8954305003 4 12 4 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 18 4 C 19.1045694997 4 20 4.89543050034 20 6 C 20 7.10456949966 19.1045694997 8 18 8 C 16.8954305003 8 16 7.10456949966 16 6 C 16 4.89543050034 16.8954305003 4 18 4 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 6 10 C 7.10456949966 10 8 10.8954305003 8 12 C 8 13.1045694997 7.10456949966 14 6 14 C 4.89543050034 14 4 13.1045694997 4 12 C 4 10.8954305003 4.89543050034 10 6 10 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 10 C 13.1045694997 10 14 10.8954305003 14 12 C 14 13.1045694997 13.1045694997 14 12 14 C 10.8954305003 14 10 13.1045694997 10 12 C 10 10.8954305003 10.8954305003 10 12 10 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 18 10 C 19.1045694997 10 20 10.8954305003 20 12 C 20 13.1045694997 19.1045694997 14 18 14 C 16.8954305003 14 16 13.1045694997 16 12 C 16 10.8954305003 16.8954305003 10 18 10 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 6 16 C 7.10456949966 16 8 16.8954305003 8 18 C 8 19.1045694997 7.10456949966 20 6 20 C 4.89543050034 20 4 19.1045694997 4 18 C 4 16.8954305003 4.89543050034 16 6 16 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 16 C 13.1045694997 16 14 16.8954305003 14 18 C 14 19.1045694997 13.1045694997 20 12 20 C 10.8954305003 20 10 19.1045694997 10 18 C 10 16.8954305003 10.8954305003 16 12 16 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 18 16 C 19.1045694997 16 20 16.8954305003 20 18 C 20 19.1045694997 19.1045694997 20 18 20 C 16.8954305003 20 16 19.1045694997 16 18 C 16 16.8954305003 16.8954305003 16 18 16 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml
index 14898c4..454b2e2 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -21,12 +21,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M7.25,18.25c0-0.41-0.34-0.75-0.75-0.75H3V8.25C3,7.01,4.01,6,5.25,6h16C21.66,6,22,5.66,22,5.25S21.66,4.5,21.25,4.5h-16 C3.18,4.5,1.5,6.18,1.5,8.25V19h5C6.91,19,7.25,18.66,7.25,18.25z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M14,16c0-1.66-1.34-3-3-3s-3,1.34-3,3s1.34,3,3,3S14,17.66,14,16z M9.5,16c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5 s-0.67,1.5-1.5,1.5S9.5,16.83,9.5,16z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20,19c1.1,0,2-0.9,2-2v-7c0-1.1-0.9-2-2-2h-3c-1.1,0-2,0.9-2,2v7c0,1.1,0.9,2,2,2H20z M16.5,17v-7 c0-0.28,0.22-0.5,0.5-0.5h3c0.28,0,0.5,0.22,0.5,0.5v7c0,0.28-0.22,0.5-0.5,0.5h-3C16.72,17.5,16.5,17.28,16.5,17z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help.xml
index 2fa1520..4e99add 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,22c0,0,0.01,0,0.01,0c5.51,0,9.98-4.46,9.99-9.98c0-0.01,0-0.01,0-0.02c0-5.52-4.48-10-10-10S2,6.48,2,12 S6.48,22,12,22z M12,3.5c4.69,0,8.5,3.81,8.5,8.52c-0.01,4.68-3.81,8.48-8.5,8.48c-4.69,0-8.5-3.81-8.5-8.5 C3.5,7.31,7.31,3.5,12,3.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M8.57,9.89c0.4,0.1,0.81-0.15,0.9-0.56c0.12-0.5,0.36-0.94,0.71-1.29c1.06-1.06,2.78-1.06,3.84,0 c0.53,0.53,0.79,1.23,0.72,1.92c-0.06,0.62-0.39,1.15-0.92,1.5c-0.17,0.11-0.35,0.19-0.52,0.27c-0.7,0.33-1.67,0.78-1.93,2.37 c-0.07,0.41,0.21,0.8,0.61,0.86C12.02,14.99,12.06,15,12.1,15c0.36,0,0.68-0.26,0.74-0.62c0.14-0.82,0.48-0.98,1.09-1.26 c0.25-0.11,0.49-0.23,0.72-0.38c0.91-0.6,1.48-1.53,1.58-2.61c0.12-1.14-0.31-2.28-1.15-3.13c-1.64-1.64-4.32-1.64-5.96,0 c-0.54,0.54-0.93,1.24-1.11,2C7.92,9.39,8.16,9.8,8.57,9.89z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 16.5 C 12.5522847498 16.5 13 16.9477152502 13 17.5 C 13 18.0522847498 12.5522847498 18.5 12 18.5 C 11.4477152502 18.5 11 18.0522847498 11 17.5 C 11 16.9477152502 11.4477152502 16.5 12 16.5 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_phone_info.xml
index efc300ab..1cafbfe 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_phone_info.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_phone_info.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M15,22c1.66,0,3-1.34,3-3V5c0-1.66-1.34-3-3-3H9C7.34,2,6,3.34,6,5v14c0,1.66,1.34,3,3,3H15z M7.5,6.5h9v11h-9V6.5z M9,3.5 h6c0.83,0,1.5,0.67,1.5,1.5h-9C7.5,4.17,8.17,3.5,9,3.5z M7.5,19h9c0,0.83-0.67,1.5-1.5,1.5H9C8.17,20.5,7.5,19.83,7.5,19z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,11.5c-0.41,0-0.75,0.34-0.75,0.75v3c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-3 C12.75,11.84,12.41,11.5,12,11.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 8 C 12.5522847498 8 13 8.44771525017 13 9 C 13 9.55228474983 12.5522847498 10 12 10 C 11.4477152502 10 11 9.55228474983 11 9 C 11 8.44771525017 11.4477152502 8 12 8 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accessibility.xml
index 7281477..4c57d8d 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accessibility.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accessibility.xml
@@ -20,18 +20,18 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M3.03,5.54c-0.11,0.4,0.13,0.81,0.53,0.92C5.24,6.91,7.07,7.2,9,7.35v8.15v3.75C9,19.66,9.34,20,9.75,20 s0.75-0.34,0.75-0.75V15.5c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5v3.75c0,0.41,0.34,0.75,0.75,0.75S15,19.66,15,19.25V15.5V7.35 c1.93-0.15,3.76-0.44,5.44-0.89c0.4-0.11,0.64-0.52,0.53-0.92c-0.11-0.4-0.51-0.64-0.92-0.53C17.64,5.66,14.93,5.98,12,5.98 S6.36,5.66,3.94,5.01C3.54,4.9,3.13,5.14,3.03,5.54z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 1 C 13.1045694997 1 14 1.89543050034 14 3 C 14 4.10456949966 13.1045694997 5 12 5 C 10.8954305003 5 10 4.10456949966 10 3 C 10 1.89543050034 10.8954305003 1 12 1 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accounts.xml
index 6b5c4e4..c63ec5b 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accounts.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_accounts.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M17,3H7C4.79,3,3,4.79,3,7v10c0,2.21,1.79,4,4,4h10c2.21,0,4-1.79,4-4V7C21,4.79,19.21,3,17,3z M17,19.5H7 c-0.93,0-1.73-0.52-2.16-1.27C6.59,16.47,9.11,15.5,12,15.5s5.41,0.97,7.16,2.73C18.73,18.98,17.93,19.5,17,19.5z M19.5,16.51 C17.52,14.89,14.92,14,12,14s-5.52,0.89-7.5,2.51V7c0-1.38,1.12-2.5,2.5-2.5h10c1.38,0,2.5,1.12,2.5,2.5V16.51z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,6c-1.93,0-3.5,1.57-3.5,3.5S10.07,13,12,13s3.5-1.57,3.5-3.5S13.93,6,12,6z M12,11.5c-1.1,0-2-0.9-2-2 c0-1.1,0.9-2,2-2c1.1,0,2,0.9,2,2C14,10.6,13.1,11.5,12,11.5z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_battery_white.xml
index d91afad..780fa2e 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_battery_white.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_battery_white.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M14,4c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1H9C7.34,4,6,5.34,6,7v12c0,1.66,1.34,3,3,3h6c1.66,0,3-1.34,3-3V7 c0-1.66-1.34-3-3-3H14z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_display_white.xml
index f526534..8dabc53 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_display_white.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_display_white.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M17,12c0-2.76-2.24-5-5-5v10C14.76,17,17,14.76,17,12z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M4,15.31V18c0,1.1,0.9,2,2,2h2.69l1.9,1.9c0.39,0.39,0.9,0.59,1.41,0.59s1.02-0.2,1.41-0.59l1.9-1.9H18c1.1,0,2-0.9,2-2 v-2.69l1.9-1.9c0.78-0.78,0.78-2.05,0-2.83L20,8.69V6c0-1.1-0.9-2-2-2h-2.69l-1.9-1.9c-0.39-0.39-0.9-0.59-1.41-0.59 s-1.02,0.2-1.41,0.59L8.69,4H6C4.9,4,4,4.9,4,6v2.69l-1.9,1.9c-0.78,0.78-0.78,2.05,0,2.83L4,15.31z M3.16,11.65l1.9-1.9L5.5,9.31 V8.69V6c0-0.28,0.22-0.5,0.5-0.5h2.69h0.62l0.44-0.44l1.9-1.9c0.13-0.13,0.28-0.15,0.35-0.15c0.08,0,0.23,0.02,0.35,0.15l1.9,1.9 l0.44,0.44h0.62H18c0.28,0,0.5,0.22,0.5,0.5v2.69v0.62l0.44,0.44l1.9,1.9c0.13,0.13,0.15,0.28,0.15,0.35s-0.02,0.23-0.15,0.35 l-1.9,1.9l-0.44,0.44v0.62V18c0,0.28-0.22,0.5-0.5,0.5h-2.69h-0.62l-0.44,0.44l-1.9,1.9c-0.13,0.13-0.28,0.15-0.35,0.15 c-0.08,0-0.23-0.02-0.35-0.15l-1.9-1.9L9.31,18.5H8.69H6c-0.28,0-0.5-0.22-0.5-0.5v-2.69v-0.62l-0.44-0.44l-1.9-1.9 C3.04,12.23,3.02,12.08,3.02,12S3.04,11.77,3.16,11.65z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_location.xml
index 213b01b..32234a1 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_location.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_location.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,21.5c0,0,7-5.34,7-11.25c0-4-3.13-7.25-7-7.25c-3.87,0-7,3.25-7,7.25C5,16.16,12,21.5,12,21.5z M12,4.5 c3.03,0,5.5,2.58,5.5,5.75c0,3.91-3.74,7.72-5.51,9.29C9.9,17.68,6.5,13.89,6.5,10.25C6.5,7.08,8.97,4.5,12,4.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M15,10c0-1.66-1.34-3-3-3c-1.66,0-3,1.34-3,3c0,1.66,1.34,3,3,3C13.66,13,15,11.66,15,10z M10.5,10 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5s-0.67,1.5-1.5,1.5S10.5,10.83,10.5,10z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_privacy.xml
index ce4c1a4..86b9a1d 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_privacy.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_privacy.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,16.5c-3.74,0-6.89-1.9-8.37-5c1.47-3.1,4.62-5,8.37-5c3.53,0,6.52,1.71,8.08,4.5h1.7C20.09,7.3,16.35,5,12,5 C7.45,5,3.57,7.51,2,11.5C3.57,15.49,7.45,18,12,18c1.41,0,2.76-0.24,4-0.7v-1.62C14.79,16.21,13.44,16.5,12,16.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,8c-1.93,0-3.5,1.57-3.5,3.5S10.07,15,12,15s3.5-1.57,3.5-3.5S13.93,8,12,8z M12,13.5c-1.1,0-2-0.9-2-2s0.9-2,2-2 c1.1,0,2,0.9,2,2S13.1,13.5,12,13.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M22,14c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2c0,0.37,0,0.7,0,1h-1v4c0,0.55,0.45,1,1,1h4c0.55,0,1-0.45,1-1v-4h-1 C22,14.65,22,14.28,22,14z M19,14c0-0.55,0.45-1,1-1s1,0.45,1,1v1h-2V14z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_security_white.xml
index 6126115..6fc58fa 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_security_white.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_security_white.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M11.25,14.79v1.46c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.46c0.45-0.26,0.75-0.74,0.75-1.29 c0-0.83-0.67-1.5-1.5-1.5s-1.5,0.67-1.5,1.5C10.5,14.05,10.8,14.53,11.25,14.79z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19,2.5c1.35,0,2.5,1.18,2.5,2.57c0,0.41,0.34,0.75,0.75,0.75S23,5.48,23,5.07C23,2.86,21.17,1,19,1s-4,1.86-4,4.07V8H5v10 c0,1.66,1.34,3,3,3h8c1.66,0,3-1.34,3-3V8h-2.5V5.07C16.5,3.68,17.65,2.5,19,2.5z M17.5,18c0,0.83-0.67,1.5-1.5,1.5H8 c-0.83,0-1.5-0.67-1.5-1.5V9.5h11V18z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
index 4adc9ce..67ddf46 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M11.99,2C6.47,2,2,6.48,2,12c0,5.52,4.47,10,9.99,10C17.52,22,22,17.52,22,12C22,6.48,17.52,2,11.99,2z M11.99,20.5 c-4.68,0-8.49-3.81-8.49-8.5c0-4.69,3.81-8.5,8.49-8.5c4.69,0,8.51,3.81,8.51,8.5C20.5,16.69,16.68,20.5,11.99,20.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,10.5c-0.41,0-0.75,0.34-0.75,0.75v5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-5 C12.75,10.84,12.41,10.5,12,10.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless.xml
index d9203d2..91670fc 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless.xml
@@ -21,15 +21,15 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19.42,11.84c-0.19,0-0.38-0.07-0.53-0.22C17.05,9.77,14.6,8.75,12,8.75s-5.05,1.02-6.89,2.86 c-0.29,0.29-0.77,0.29-1.06,0c-0.29-0.29-0.29-0.77,0-1.06C6.17,8.43,9,7.25,12,7.25s5.83,1.17,7.95,3.3 c0.29,0.29,0.29,0.77,0,1.06C19.8,11.76,19.61,11.84,19.42,11.84z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M22.61,8.65c-0.19,0-0.38-0.07-0.53-0.22C19.38,5.74,15.81,4.25,12,4.25S4.62,5.74,1.92,8.43c-0.29,0.29-0.77,0.29-1.06,0 s-0.29-0.77,0-1.06C3.84,4.39,7.79,2.75,12,2.75s8.16,1.64,11.14,4.61c0.29,0.29,0.29,0.77,0,1.06 C22.99,8.57,22.8,8.65,22.61,8.65z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M16.25,15c-0.19,0-0.38-0.07-0.53-0.22c-1-0.99-2.32-1.53-3.73-1.53s-2.73,0.54-3.73,1.53c-0.29,0.29-0.77,0.29-1.06-0.01 s-0.29-0.77,0.01-1.06c1.28-1.27,2.98-1.96,4.78-1.96s3.5,0.7,4.78,1.96c0.29,0.29,0.3,0.77,0.01,1.06 C16.64,14.93,16.45,15,16.25,15z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage_white.xml
index cf9db68..807c3bf 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage_white.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_storage_white.xml
@@ -20,21 +20,21 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M21,17c0-1.1-0.9-2-2-2H5c-1.1,0-2,0.9-2,2v3h18V17z M19.5,18.5h-15V17c0-0.28,0.22-0.5,0.5-0.5h14 c0.28,0,0.5,0.22,0.5,0.5V18.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M21,5c0-1.1-0.9-2-2-2H5C3.9,3,3,3.9,3,5v3h18V5z M19.5,6.5h-15V5c0-0.28,0.22-0.5,0.5-0.5h14c0.28,0,0.5,0.22,0.5,0.5V6.5 z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M21,11c0-1.1-0.9-2-2-2H5c-1.1,0-2,0.9-2,2v3h18V11z M19.5,12.5h-15V11c0-0.28,0.22-0.5,0.5-0.5h14 c0.28,0,0.5,0.22,0.5,0.5V12.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 6.01 4.75 C 6.42421356237 4.75 6.76 5.08578643763 6.76 5.5 C 6.76 5.91421356237 6.42421356237 6.25 6.01 6.25 C 5.59578643763 6.25 5.26 5.91421356237 5.26 5.5 C 5.26 5.08578643763 5.59578643763 4.75 6.01 4.75 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 6.01 10.75 C 6.42421356237 10.75 6.76 11.0857864376 6.76 11.5 C 6.76 11.9142135624 6.42421356237 12.25 6.01 12.25 C 5.59578643763 12.25 5.26 11.9142135624 5.26 11.5 C 5.26 11.0857864376 5.59578643763 10.75 6.01 10.75 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 6.01 16.75 C 6.42421356237 16.75 6.76 17.0857864376 6.76 17.5 C 6.76 17.9142135624 6.42421356237 18.25 6.01 18.25 C 5.59578643763 18.25 5.26 17.9142135624 5.26 17.5 C 5.26 17.0857864376 5.59578643763 16.75 6.01 16.75 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
index ace87e0..1a06137 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M14.44,13.56c-0.38,0.17-0.54,0.62-0.37,0.99c0.13,0.28,0.4,0.44,0.68,0.44c0.1,0,0.21-0.02,0.31-0.07 C16.26,14.37,17,13.25,17,12c0-1.25-0.74-2.37-1.93-2.93c-0.37-0.17-0.82-0.01-1,0.37c-0.17,0.38-0.01,0.82,0.36,1 c0.66,0.3,1.07,0.9,1.07,1.57S15.09,13.26,14.44,13.56z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M14.59,17.42c-0.4,0.09-0.66,0.49-0.57,0.9c0.08,0.35,0.39,0.59,0.73,0.59c0.05,0,0.11-0.01,0.16-0.02 c3.29-0.74,5.59-3.57,5.59-6.89s-2.3-6.15-5.59-6.89c-0.41-0.08-0.81,0.17-0.9,0.57s0.16,0.8,0.57,0.9C17.19,7.16,19,9.39,19,12 S17.19,16.84,14.59,17.42z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M7,15l4.15,4.15c0.1,0.1,0.23,0.15,0.35,0.15c0.26,0,0.5-0.2,0.5-0.5V5.21c0-0.3-0.25-0.5-0.5-0.5 c-0.12,0-0.25,0.05-0.35,0.15L7,9H5c-1.1,0-2,0.9-2,2v2c0,1.1,0.9,2,2,2H7z M4.5,13v-2c0-0.28,0.22-0.5,0.5-0.5h2.62l2.88-2.88 v8.76L7.62,13.5H5C4.72,13.5,4.5,13.28,4.5,13z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_apps.xml
index 60b5116..74b13fd 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_apps.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_apps.xml
@@ -20,30 +20,30 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M7.5,4h-3C4.22,4,4,4.22,4,4.5v3C4,7.78,4.22,8,4.5,8h3C7.78,8,8,7.78,8,7.5v-3C8,4.22,7.78,4,7.5,4z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M13.5,4h-3C10.22,4,10,4.22,10,4.5v3C10,7.78,10.22,8,10.5,8h3C13.78,8,14,7.78,14,7.5v-3C14,4.22,13.78,4,13.5,4z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19.5,4h-3C16.22,4,16,4.22,16,4.5v3C16,7.78,16.22,8,16.5,8h3C19.78,8,20,7.78,20,7.5v-3C20,4.22,19.78,4,19.5,4z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M7.5,10h-3C4.22,10,4,10.22,4,10.5v3C4,13.78,4.22,14,4.5,14h3C7.78,14,8,13.78,8,13.5v-3C8,10.22,7.78,10,7.5,10z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M13.5,10h-3c-0.28,0-0.5,0.22-0.5,0.5v3c0,0.28,0.22,0.5,0.5,0.5h3c0.28,0,0.5-0.22,0.5-0.5v-3C14,10.22,13.78,10,13.5,10 z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19.5,10h-3c-0.28,0-0.5,0.22-0.5,0.5v3c0,0.28,0.22,0.5,0.5,0.5h3c0.28,0,0.5-0.22,0.5-0.5v-3C20,10.22,19.78,10,19.5,10 z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M7.5,16h-3C4.22,16,4,16.22,4,16.5v3C4,19.78,4.22,20,4.5,20h3C7.78,20,8,19.78,8,19.5v-3C8,16.22,7.78,16,7.5,16z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M13.5,16h-3c-0.28,0-0.5,0.22-0.5,0.5v3c0,0.28,0.22,0.5,0.5,0.5h3c0.28,0,0.5-0.22,0.5-0.5v-3C14,16.22,13.78,16,13.5,16 z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19.5,16h-3c-0.28,0-0.5,0.22-0.5,0.5v3c0,0.28,0.22,0.5,0.5,0.5h3c0.28,0,0.5-0.22,0.5-0.5v-3C20,16.22,19.78,16,19.5,16 z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml
index a451ef8..33a4b29 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -21,12 +21,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M6,18H3V6h17c0.55,0,1-0.45,1-1s-0.45-1-1-1H3C1.9,4,1,4.9,1,6v12c0,1.1,0.9,2,2,2h3c0.55,0,1-0.45,1-1S6.55,18,6,18z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M13,12H9v1.78C8.39,14.33,8,15.11,8,16s0.39,1.67,1,2.22V20h4v-1.78c0.61-0.55,1-1.34,1-2.22s-0.39-1.67-1-2.22V12z M11,17.5c-0.83,0-1.5-0.67-1.5-1.5c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C12.5,16.83,11.83,17.5,11,17.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M22,8h-6c-0.5,0-1,0.5-1,1v10c0,0.5,0.5,1,1,1h6c0.5,0,1-0.5,1-1V9C23,8.5,22.5,8,22,8z M21,18h-4v-8h4V18z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help.xml
index 25bb103..42854a4 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,22c5.52,0,10-4.48,10-10c0-5.52-4.48-10-10-10S2,6.48,2,12C2,17.52,6.48,22,12,22z M12,18.96 c-0.69,0-1.25-0.56-1.25-1.25c0-0.69,0.56-1.25,1.25-1.25s1.25,0.56,1.25,1.25C13.25,18.4,12.69,18.96,12,18.96z M8.16,7.92 c0.63-2.25,2.91-3.38,5.05-2.74c1.71,0.51,2.84,2.16,2.78,3.95c-0.07,2.44-2.49,2.61-2.92,5.06c-0.09,0.52-0.59,0.87-1.13,0.79 c-0.57-0.08-0.94-0.66-0.83-1.23c0.52-2.61,2.66-2.84,2.87-4.5c0.12-0.96-0.42-1.87-1.34-2.17c-1.04-0.33-2.21,0.16-2.55,1.37 C9.97,8.9,9.57,9.19,9.12,9.19C8.46,9.19,7.99,8.56,8.16,7.92z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_phone_info.xml
index 6821259..e932b9b 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_phone_info.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_phone_info.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M17,1.01L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1.01,17,1.01z M17,19H7V5h10V19z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 7 C 12.6903559373 7 13.25 7.55964406271 13.25 8.25 C 13.25 8.94035593729 12.6903559373 9.5 12 9.5 C 11.3096440627 9.5 10.75 8.94035593729 10.75 8.25 C 10.75 7.55964406271 11.3096440627 7 12 7 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,11c-0.55,0-1,0.4-1,0.9v4.21c0,0.5,0.45,0.9,1,0.9s1-0.4,1-0.9V11.9C13,11.4,12.55,11,12,11z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accessibility.xml
index 762b7d4..db45638 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accessibility.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accessibility.xml
@@ -20,18 +20,18 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.76,5.02l-0.02-0.06c-0.13-0.53-0.67-0.85-1.2-0.73C17.16,4.77,14.49,5,12,5S6.84,4.77,4.46,4.24 c-0.54-0.12-1.07,0.19-1.2,0.73L3.24,5.02C3.11,5.56,3.43,6.12,3.97,6.24C5.59,6.61,7.34,6.86,9,7v12c0,0.55,0.45,1,1,1 s1-0.45,1-1v-5h2v5c0,0.55,0.45,1,1,1s1-0.45,1-1V7c1.66-0.14,3.41-0.39,5.03-0.76C20.57,6.12,20.89,5.56,20.76,5.02z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 0 C 13.1045694997 0 14 0.895430500338 14 2 C 14 3.10456949966 13.1045694997 4 12 4 C 10.8954305003 4 10 3.10456949966 10 2 C 10 0.895430500338 10.8954305003 0 12 0 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accounts.xml
index 5409d0d..0d4a244 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accounts.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_accounts.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M12,6c1.93,0,3.5,1.57,3.5,3.5 S13.93,13,12,13s-3.5-1.57-3.5-3.5S10.07,6,12,6z M19,19H5v-1.36c0-0.74,0.41-1.44,1.07-1.77C7.24,15.28,9.3,14.5,12,14.5 s4.76,0.78,5.93,1.37C18.59,16.2,19,16.9,19,17.64V19z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_battery_white.xml
index 0fea7ae..bb11388 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_battery_white.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_battery_white.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M10,2v2H8.33C7.6,4,7,4.6,7,5.33v15.33C7,21.4,7.6,22,8.33,22h7.33C16.4,22,17,21.4,17,20.67V5.33C17,4.6,16.4,4,15.67,4 H14V2H10z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_display_white.xml
index b75787b..2c931e4 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_display_white.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_display_white.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M4,15.3V19c0,0.55,0.45,1,1,1h3.69l2.6,2.6c0.39,0.39,1.02,0.39,1.41,0l2.6-2.6H19c0.55,0,1-0.45,1-1v-3.69l2.6-2.6 c0.39-0.39,0.39-1.02,0-1.41L20,8.69V5c0-0.55-0.45-1-1-1h-3.69l-2.6-2.6c-0.39-0.39-1.02-0.39-1.41,0L8.69,4H5C4.45,4,4,4.45,4,5 v3.69l-2.6,2.6c-0.39,0.39-0.39,1.02,0,1.41L4,15.3z M12,6c3.31,0,6,2.69,6,6s-2.69,6-6,6V6z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_location.xml
index ecab3a3..8732ea5 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_location.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_location.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12.77,21.11C14.58,18.92,19,13.17,19,9c0-3.87-3.13-7-7-7S5,5.13,5,9c0,4.17,4.42,9.92,6.24,12.11 C11.64,21.59,12.37,21.59,12.77,21.11z M9.5,9c0-1.38,1.12-2.5,2.5-2.5s2.5,1.12,2.5,2.5c0,1.38-1.12,2.5-2.5,2.5S9.5,10.38,9.5,9z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_privacy.xml
index 4404530..2ebdc8f 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_privacy.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_privacy.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M16.48,11.7c0.74-0.44,1.6-0.7,2.52-0.7h3.78C20.93,6.88,16.81,4,12,4C7,4,2.73,7.11,1,11.5C2.73,15.89,7,19,12,19 c0.68,0,1.35-0.06,2-0.17V16c0-0.18,0.03-0.34,0.05-0.51C13.43,15.8,12.74,16,12,16c-2.49,0-4.5-2.01-4.5-4.5 C7.5,9.01,9.51,7,12,7s4.5,2.01,4.5,4.5C16.5,11.57,16.48,11.64,16.48,11.7z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 9 C 13.3807118746 9 14.5 10.1192881254 14.5 11.5 C 14.5 12.8807118746 13.3807118746 14 12 14 C 10.6192881254 14 9.5 12.8807118746 9.5 11.5 C 9.5 10.1192881254 10.6192881254 9 12 9 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M22,16v-0.5c0-1.4-1.1-2.5-2.5-2.5S17,14.1,17,15.5V16c-0.5,0-1,0.5-1,1v4c0,0.5,0.5,1,1,1h5c0.5,0,1-0.5,1-1v-4 C23,16.5,22.5,16,22,16z M20.5,16h-2v-0.5c0-0.53,0.47-1,1-1s1,0.47,1,1V16z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_security_white.xml
index 86147c2..ecaed01 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_security_white.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_security_white.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M18,1c-2.21,0-4,1.79-4,4v3H6c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V10c0-1.1-0.9-2-2-2h-2V5 c0-1.1,0.9-2,2-2s2,0.9,2,2c0,0.55,0.45,1,1,1s1-0.45,1-1C22,2.79,20.21,1,18,1z M12,17c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2 s2,0.9,2,2C14,16.1,13.1,17,12,17z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
index ce233b7..659a926 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M13,17c0,0.55-0.45,1-1,1s-1-0.45-1-1 v-5c0-0.55,0.45-1,1-1s1,0.45,1,1V17z M12,9.25c-0.69,0-1.25-0.56-1.25-1.25S11.31,6.75,12,6.75S13.25,7.31,13.25,8 S12.69,9.25,12,9.25z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless.xml
index 92dbd29..6e80d13 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless.xml
@@ -21,12 +21,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M11.29,19.29c0.39,0.39,1.03,0.4,1.42,0L14,18c0.47-0.47,0.38-1.28-0.22-1.58C13.25,16.15,12.64,16,12,16 c-0.64,0-1.24,0.15-1.77,0.41c-0.59,0.29-0.69,1.11-0.22,1.58L11.29,19.29z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M17.6,14.39l0.71-0.71c0.42-0.42,0.39-1.12-0.08-1.5C16.52,10.82,14.35,10,12,10c-2.34,0-4.5,0.81-6.21,2.17 c-0.47,0.37-0.51,1.07-0.09,1.49l0.71,0.71c0.35,0.36,0.92,0.39,1.32,0.08C8.91,13.54,10.39,13,12,13c1.61,0,3.1,0.55,4.29,1.47 C16.69,14.78,17.25,14.75,17.6,14.39z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M21.83,10.16l0.71-0.71c0.42-0.42,0.38-1.09-0.06-1.48C19.68,5.5,16.01,4,12,4C8.01,4,4.36,5.49,1.56,7.94 C1.12,8.33,1.08,9,1.49,9.41l0.71,0.71c0.37,0.37,0.96,0.4,1.35,0.06C5.81,8.2,8.77,7,12,7c3.25,0,6.22,1.22,8.49,3.22 C20.88,10.56,21.47,10.53,21.83,10.16z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage_white.xml
index 03780db..9eb336c 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage_white.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_storage_white.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19,10H5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2C21,10.9,20.1,10,19,10z M6,13.1c-0.61,0-1.1-0.49-1.1-1.1 s0.49-1.1,1.1-1.1s1.1,0.49,1.1,1.1S6.61,13.1,6,13.1z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M21,18c0-1.1-0.9-2-2-2H5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h14C20.1,20,21,19.1,21,18z M6,19.1c-0.61,0-1.1-0.49-1.1-1.1 s0.49-1.1,1.1-1.1s1.1,0.49,1.1,1.1S6.61,19.1,6,19.1z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19,4H5C3.9,4,3,4.9,3,6c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2C21,4.9,20.1,4,19,4z M6,7.1C5.39,7.1,4.9,6.61,4.9,6 S5.39,4.9,6,4.9S7.1,5.39,7.1,6S6.61,7.1,6,7.1z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
index 863df71..b940351 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.4,8.78c-0.91-2.39-2.8-4.27-5.18-5.18C14.63,3.37,14,3.83,14,4.46v0.19c0,0.38,0.25,0.71,0.61,0.85 C17.18,6.54,19,9.06,19,12s-1.82,5.46-4.39,6.5C14.25,18.64,14,18.97,14,19.35v0.19c0,0.63,0.63,1.08,1.22,0.86 C19.86,18.62,22.18,13.42,20.4,8.78z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M16.5,12c0-1.71-0.97-3.27-2.5-4.03v8.05C15.48,15.29,16.5,13.77,16.5,12z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M10.29,5.7L7,9H4c-0.55,0-1,0.45-1,1v4c0,0.55,0.45,1,1,1h3l3.29,3.29c0.63,0.63,1.71,0.18,1.71-0.71V6.41 C12,5.52,10.92,5.07,10.29,5.7z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_apps.xml
index 58999d0..5b1850f 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_apps.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_apps.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M 6 4 C 7.10456949966 4 8 4.89543050034 8 6 C 8 7.10456949966 7.10456949966 8 6 8 C 4.89543050034 8 4 7.10456949966 4 6 C 4 4.89543050034 4.89543050034 4 6 4 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 4 C 13.1045694997 4 14 4.89543050034 14 6 C 14 7.10456949966 13.1045694997 8 12 8 C 10.8954305003 8 10 7.10456949966 10 6 C 10 4.89543050034 10.8954305003 4 12 4 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 18 4 C 19.1045694997 4 20 4.89543050034 20 6 C 20 7.10456949966 19.1045694997 8 18 8 C 16.8954305003 8 16 7.10456949966 16 6 C 16 4.89543050034 16.8954305003 4 18 4 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 6 10 C 7.10456949966 10 8 10.8954305003 8 12 C 8 13.1045694997 7.10456949966 14 6 14 C 4.89543050034 14 4 13.1045694997 4 12 C 4 10.8954305003 4.89543050034 10 6 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 10 C 13.1045694997 10 14 10.8954305003 14 12 C 14 13.1045694997 13.1045694997 14 12 14 C 10.8954305003 14 10 13.1045694997 10 12 C 10 10.8954305003 10.8954305003 10 12 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 18 10 C 19.1045694997 10 20 10.8954305003 20 12 C 20 13.1045694997 19.1045694997 14 18 14 C 16.8954305003 14 16 13.1045694997 16 12 C 16 10.8954305003 16.8954305003 10 18 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 6 16 C 7.10456949966 16 8 16.8954305003 8 18 C 8 19.1045694997 7.10456949966 20 6 20 C 4.89543050034 20 4 19.1045694997 4 18 C 4 16.8954305003 4.89543050034 16 6 16 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 16 C 13.1045694997 16 14 16.8954305003 14 18 C 14 19.1045694997 13.1045694997 20 12 20 C 10.8954305003 20 10 19.1045694997 10 18 C 10 16.8954305003 10.8954305003 16 12 16 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 18 16 C 19.1045694997 16 20 16.8954305003 20 18 C 20 19.1045694997 19.1045694997 20 18 20 C 16.8954305003 20 16 19.1045694997 16 18 C 16 16.8954305003 16.8954305003 16 18 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 6 4 C 7.10456949966 4 8 4.89543050034 8 6 C 8 7.10456949966 7.10456949966 8 6 8 C 4.89543050034 8 4 7.10456949966 4 6 C 4 4.89543050034 4.89543050034 4 6 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 4 C 13.1045694997 4 14 4.89543050034 14 6 C 14 7.10456949966 13.1045694997 8 12 8 C 10.8954305003 8 10 7.10456949966 10 6 C 10 4.89543050034 10.8954305003 4 12 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 18 4 C 19.1045694997 4 20 4.89543050034 20 6 C 20 7.10456949966 19.1045694997 8 18 8 C 16.8954305003 8 16 7.10456949966 16 6 C 16 4.89543050034 16.8954305003 4 18 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 6 10 C 7.10456949966 10 8 10.8954305003 8 12 C 8 13.1045694997 7.10456949966 14 6 14 C 4.89543050034 14 4 13.1045694997 4 12 C 4 10.8954305003 4.89543050034 10 6 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 10 C 13.1045694997 10 14 10.8954305003 14 12 C 14 13.1045694997 13.1045694997 14 12 14 C 10.8954305003 14 10 13.1045694997 10 12 C 10 10.8954305003 10.8954305003 10 12 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 18 10 C 19.1045694997 10 20 10.8954305003 20 12 C 20 13.1045694997 19.1045694997 14 18 14 C 16.8954305003 14 16 13.1045694997 16 12 C 16 10.8954305003 16.8954305003 10 18 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 6 16 C 7.10456949966 16 8 16.8954305003 8 18 C 8 19.1045694997 7.10456949966 20 6 20 C 4.89543050034 20 4 19.1045694997 4 18 C 4 16.8954305003 4.89543050034 16 6 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 16 C 13.1045694997 16 14 16.8954305003 14 18 C 14 19.1045694997 13.1045694997 20 12 20 C 10.8954305003 20 10 19.1045694997 10 18 C 10 16.8954305003 10.8954305003 16 12 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 18 16 C 19.1045694997 16 20 16.8954305003 20 18 C 20 19.1045694997 19.1045694997 20 18 20 C 16.8954305003 20 16 19.1045694997 16 18 C 16 16.8954305003 16.8954305003 16 18 16 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_devices_other.xml
index fa91107..954ff32 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M2.51,17.74V6.27c0-0.41,0.34-0.75,0.75-0.75H21v-1.5H3.26c-1.24,0-2.25,1.01-2.25,2.25v11.46c0,1.24,1.01,2.25,2.25,2.25 H7v-1.5H3.26C2.85,18.49,2.51,18.15,2.51,17.74z"/>
- <path android:fillColor="@android:color/white" android:pathData="M20.75,8h-3.5C16.01,8,15,9.01,15,10.25v7.5c0,1.24,1.01,2.25,2.25,2.25h3.5c1.24,0,2.25-1.01,2.25-2.25v-7.5 C23,9.01,21.99,8,20.75,8z M21.5,17.75c0,0.41-0.34,0.75-0.75,0.75h-3.5c-0.41,0-0.75-0.34-0.75-0.75v-7.5 c0-0.41,0.34-0.75,0.75-0.75h3.5c0.41,0,0.75,0.34,0.75,0.75V17.75z"/>
- <path android:fillColor="@android:color/white" android:pathData="M13,13.84v-1.09c0-0.41-0.34-0.75-0.75-0.75h-2.5C9.34,12,9,12.34,9,12.75v1.09C8.54,14.25,8.18,14.92,8.18,16 c0,1.09,0.36,1.75,0.82,2.16v1.09C9,19.66,9.34,20,9.75,20h2.5c0.41,0,0.75-0.34,0.75-0.75v-1.09c0.46-0.41,0.82-1.08,0.82-2.16 C13.82,14.91,13.46,14.25,13,13.84z M11,17.25C10.03,17.26,9.75,16.9,9.75,16c0-0.9,0.3-1.25,1.25-1.25 c0.95-0.01,1.25,0.33,1.25,1.25C12.25,16.84,11.98,17.25,11,17.25z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M2.51,17.74V6.27c0-0.41,0.34-0.75,0.75-0.75H21v-1.5H3.26c-1.24,0-2.25,1.01-2.25,2.25v11.46c0,1.24,1.01,2.25,2.25,2.25 H7v-1.5H3.26C2.85,18.49,2.51,18.15,2.51,17.74z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M20.75,8h-3.5C16.01,8,15,9.01,15,10.25v7.5c0,1.24,1.01,2.25,2.25,2.25h3.5c1.24,0,2.25-1.01,2.25-2.25v-7.5 C23,9.01,21.99,8,20.75,8z M21.5,17.75c0,0.41-0.34,0.75-0.75,0.75h-3.5c-0.41,0-0.75-0.34-0.75-0.75v-7.5 c0-0.41,0.34-0.75,0.75-0.75h3.5c0.41,0,0.75,0.34,0.75,0.75V17.75z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M13,13.84v-1.09c0-0.41-0.34-0.75-0.75-0.75h-2.5C9.34,12,9,12.34,9,12.75v1.09C8.54,14.25,8.18,14.92,8.18,16 c0,1.09,0.36,1.75,0.82,2.16v1.09C9,19.66,9.34,20,9.75,20h2.5c0.41,0,0.75-0.34,0.75-0.75v-1.09c0.46-0.41,0.82-1.08,0.82-2.16 C13.82,14.91,13.46,14.25,13,13.84z M11,17.25C10.03,17.26,9.75,16.9,9.75,16c0-0.9,0.3-1.25,1.25-1.25 c0.95-0.01,1.25,0.33,1.25,1.25C12.25,16.84,11.98,17.25,11,17.25z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_help.xml
index 8ab01a6..89b8031 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_help.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_help.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M13.73,6.41c-0.51-0.27-1.09-0.4-1.74-0.4c-0.87,0-1.58,0.24-2.13,0.73C9.31,7.22,8.91,7.78,8.67,8.42l1.29,0.54 c0.16-0.46,0.41-0.84,0.73-1.16c0.32-0.31,0.76-0.47,1.3-0.47c0.6,0,1.07,0.16,1.41,0.48c0.34,0.32,0.51,0.75,0.51,1.27 c0,0.39-0.1,0.73-0.29,1.01c-0.19,0.28-0.51,0.61-0.94,1.01c-0.54,0.5-0.91,0.93-1.11,1.29c-0.21,0.36-0.31,0.81-0.31,1.36v0.79 h1.43v-0.69c0-0.39,0.08-0.74,0.25-1.03c0.16-0.29,0.43-0.61,0.79-0.93c0.47-0.43,0.85-0.85,1.15-1.27 c0.3-0.42,0.45-0.93,0.45-1.53c0-0.58-0.14-1.1-0.42-1.57C14.63,7.05,14.24,6.68,13.73,6.41z"/>
- <path android:fillColor="@android:color/white" android:pathData="M11.98,15.96c-0.03,0-1-0.06-1,1c0,1.06,0.96,1,1,1c0.03,0,1,0.06,1-1C12.98,15.9,12.02,15.96,11.98,15.96z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12,2C4.41,2,2,6.9,2,12c0,5.09,2.35,10,10,10c7.59,0,10-4.9,10-10C22,6.91,19.65,2,12,2z M12,20.5 c-2.64,0.05-8.5-0.59-8.5-8.5c0-7.91,5.88-8.55,8.5-8.5c2.64-0.05,8.5,0.59,8.5,8.5C20.5,19.91,14.62,20.55,12,20.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M13.73,6.41c-0.51-0.27-1.09-0.4-1.74-0.4c-0.87,0-1.58,0.24-2.13,0.73C9.31,7.22,8.91,7.78,8.67,8.42l1.29,0.54 c0.16-0.46,0.41-0.84,0.73-1.16c0.32-0.31,0.76-0.47,1.3-0.47c0.6,0,1.07,0.16,1.41,0.48c0.34,0.32,0.51,0.75,0.51,1.27 c0,0.39-0.1,0.73-0.29,1.01c-0.19,0.28-0.51,0.61-0.94,1.01c-0.54,0.5-0.91,0.93-1.11,1.29c-0.21,0.36-0.31,0.81-0.31,1.36v0.79 h1.43v-0.69c0-0.39,0.08-0.74,0.25-1.03c0.16-0.29,0.43-0.61,0.79-0.93c0.47-0.43,0.85-0.85,1.15-1.27 c0.3-0.42,0.45-0.93,0.45-1.53c0-0.58-0.14-1.1-0.42-1.57C14.63,7.05,14.24,6.68,13.73,6.41z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M11.98,15.96c-0.03,0-1-0.06-1,1c0,1.06,0.96,1,1,1c0.03,0,1,0.06,1-1C12.98,15.9,12.02,15.96,11.98,15.96z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,2C4.41,2,2,6.9,2,12c0,5.09,2.35,10,10,10c7.59,0,10-4.9,10-10C22,6.91,19.65,2,12,2z M12,20.5 c-2.64,0.05-8.5-0.59-8.5-8.5c0-7.91,5.88-8.55,8.5-8.5c2.64-0.05,8.5,0.59,8.5,8.5C20.5,19.91,14.62,20.55,12,20.5z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_phone_info.xml
index 2edda9c..e2246ce 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_phone_info.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_phone_info.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M16.75,1h-9.5C6.01,1,5,2.01,5,3.25v17.5C5,21.99,6.01,23,7.25,23h9.5c1.24,0,2.25-1.01,2.25-2.25V3.25 C19,2.01,17.99,1,16.75,1z M7.25,2.5h9.5c0.41,0,0.75,0.34,0.75,0.75v1h-11v-1C6.5,2.84,6.84,2.5,7.25,2.5z M17.5,5.75v12.5h-11 V5.75H17.5z M16.75,21.5h-9.5c-0.41,0-0.75-0.34-0.75-0.75v-1h11v1C17.5,21.16,17.16,21.5,16.75,21.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 11.25 11 H 12.75 V 16 H 11.25 V 11 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 8 C 12.4142135624 8 12.75 8.33578643763 12.75 8.75 C 12.75 9.16421356237 12.4142135624 9.5 12 9.5 C 11.5857864376 9.5 11.25 9.16421356237 11.25 8.75 C 11.25 8.33578643763 11.5857864376 8 12 8 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M16.75,1h-9.5C6.01,1,5,2.01,5,3.25v17.5C5,21.99,6.01,23,7.25,23h9.5c1.24,0,2.25-1.01,2.25-2.25V3.25 C19,2.01,17.99,1,16.75,1z M7.25,2.5h9.5c0.41,0,0.75,0.34,0.75,0.75v1h-11v-1C6.5,2.84,6.84,2.5,7.25,2.5z M17.5,5.75v12.5h-11 V5.75H17.5z M16.75,21.5h-9.5c-0.41,0-0.75-0.34-0.75-0.75v-1h11v1C17.5,21.16,17.16,21.5,16.75,21.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 11.25 11 H 12.75 V 16 H 11.25 V 11 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 8 C 12.4142135624 8 12.75 8.33578643763 12.75 8.75 C 12.75 9.16421356237 12.4142135624 9.5 12 9.5 C 11.5857864376 9.5 11.25 9.16421356237 11.25 8.75 C 11.25 8.33578643763 11.5857864376 8 12 8 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_accessibility.xml
index 900a3a6..a92595b 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_accessibility.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_accessibility.xml
@@ -14,9 +14,9 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 0 C 13.1045694997 0 14 0.895430500338 14 2 C 14 3.10456949966 13.1045694997 4 12 4 C 10.8954305003 4 10 3.10456949966 10 2 C 10 0.895430500338 10.8954305003 0 12 0 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M15,20V7c2-0.17,4.14-0.5,6-1l-0.5-2c-2.61,0.7-5.67,1-8.5,1S6.11,4.7,3.5,4L3,6c1.86,0.5,4,0.83,6,1v13h2v-6h2v6H15z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 0 C 13.1045694997 0 14 0.895430500338 14 2 C 14 3.10456949966 13.1045694997 4 12 4 C 10.8954305003 4 10 3.10456949966 10 2 C 10 0.895430500338 10.8954305003 0 12 0 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M15,20V7c2-0.17,4.14-0.5,6-1l-0.5-2c-2.61,0.7-5.67,1-8.5,1S6.11,4.7,3.5,4L3,6c1.86,0.5,4,0.83,6,1v13h2v-6h2v6H15z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_accounts.xml
index 0a7ec3f..b17efd1 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_accounts.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_accounts.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M18.75,3H5.25C4.01,3,3,4.01,3,5.25v13.5C3,19.99,4.01,21,5.25,21h13.5c1.24,0,2.25-1.01,2.25-2.25V5.25 C21,4.01,19.99,3,18.75,3z M18.75,19.5H5.25c-0.35,0-0.64-0.25-0.72-0.58C4.9,18.6,7.23,16.4,12,16.51 c4.77-0.11,7.11,2.1,7.47,2.41C19.39,19.25,19.1,19.5,18.75,19.5z M19.5,17.03c-3.24-2.22-7.05-2.02-7.5-2.02 c-0.46,0-4.27-0.19-7.5,2.02V5.25c0-0.41,0.34-0.75,0.75-0.75h13.5c0.41,0,0.75,0.34,0.75,0.75V17.03z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12,6C9.33,6,8.5,7.73,8.5,9.5c0,1.78,0.83,3.5,3.5,3.5c2.67,0,3.5-1.73,3.5-3.5C15.5,7.72,14.67,6,12,6z M12,11.5 c-0.43,0.01-2,0.13-2-2c0-2.14,1.58-2,2-2c0.43-0.01,2-0.13,2,2C14,11.64,12.42,11.5,12,11.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M18.75,3H5.25C4.01,3,3,4.01,3,5.25v13.5C3,19.99,4.01,21,5.25,21h13.5c1.24,0,2.25-1.01,2.25-2.25V5.25 C21,4.01,19.99,3,18.75,3z M18.75,19.5H5.25c-0.35,0-0.64-0.25-0.72-0.58C4.9,18.6,7.23,16.4,12,16.51 c4.77-0.11,7.11,2.1,7.47,2.41C19.39,19.25,19.1,19.5,18.75,19.5z M19.5,17.03c-3.24-2.22-7.05-2.02-7.5-2.02 c-0.46,0-4.27-0.19-7.5,2.02V5.25c0-0.41,0.34-0.75,0.75-0.75h13.5c0.41,0,0.75,0.34,0.75,0.75V17.03z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,6C9.33,6,8.5,7.73,8.5,9.5c0,1.78,0.83,3.5,3.5,3.5c2.67,0,3.5-1.73,3.5-3.5C15.5,7.72,14.67,6,12,6z M12,11.5 c-0.43,0.01-2,0.13-2-2c0-2.14,1.58-2,2-2c0.43-0.01,2-0.13,2,2C14,11.64,12.42,11.5,12,11.5z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_battery_white.xml
index cc80eb7..4af4806 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_battery_white.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_battery_white.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M16,4h-1V2.5C15,2.22,14.78,2,14.5,2h-5C9.22,2,9,2.22,9,2.5V4H8C6.9,4,6,4.9,6,6v12c0,2.21,1.79,4,4,4h4 c2.21,0,4-1.79,4-4V6C18,4.9,17.1,4,16,4z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M16,4h-1V2.5C15,2.22,14.78,2,14.5,2h-5C9.22,2,9,2.22,9,2.5V4H8C6.9,4,6,4.9,6,6v12c0,2.21,1.79,4,4,4h4 c2.21,0,4-1.79,4-4V6C18,4.9,17.1,4,16,4z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_display_white.xml
index d4d4174..9eb8a0b 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_display_white.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_display_white.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,7V17c0.17,0,5,0.31,5-5C17,6.7,12.22,7,12,7z"/>
- <path android:fillColor="@android:color/white" android:pathData="M22.78,11.47L20,8.69V4.75C20,4.34,19.66,4,19.25,4h-3.94l-2.78-2.78c-0.29-0.29-0.77-0.29-1.06,0L8.69,4H4.75 C4.34,4,4,4.34,4,4.75v3.94l-2.78,2.78c-0.29,0.29-0.29,0.77,0,1.06L4,15.31v3.94C4,19.66,4.34,20,4.75,20h3.94l2.78,2.78 C11.62,22.93,11.81,23,12,23s0.38-0.07,0.53-0.22L15.31,20h3.94c0.41,0,0.75-0.34,0.75-0.75v-3.94l2.78-2.78 C23.07,12.24,23.07,11.76,22.78,11.47z M18.72,14.47C18.58,14.61,18.5,14.8,18.5,15v3.5H15c-0.2,0-0.39,0.08-0.53,0.22L12,21.19 l-2.47-2.47C9.39,18.58,9.2,18.5,9,18.5H5.5V15c0-0.2-0.08-0.39-0.22-0.53L2.81,12l2.47-2.47C5.42,9.39,5.5,9.2,5.5,9V5.5H9 c0.2,0,0.39-0.08,0.53-0.22L12,2.81l2.47,2.47C14.61,5.42,14.8,5.5,15,5.5h3.5V9c0,0.2,0.08,0.39,0.22,0.53L21.19,12L18.72,14.47z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,7V17c0.17,0,5,0.31,5-5C17,6.7,12.22,7,12,7z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M22.78,11.47L20,8.69V4.75C20,4.34,19.66,4,19.25,4h-3.94l-2.78-2.78c-0.29-0.29-0.77-0.29-1.06,0L8.69,4H4.75 C4.34,4,4,4.34,4,4.75v3.94l-2.78,2.78c-0.29,0.29-0.29,0.77,0,1.06L4,15.31v3.94C4,19.66,4.34,20,4.75,20h3.94l2.78,2.78 C11.62,22.93,11.81,23,12,23s0.38-0.07,0.53-0.22L15.31,20h3.94c0.41,0,0.75-0.34,0.75-0.75v-3.94l2.78-2.78 C23.07,12.24,23.07,11.76,22.78,11.47z M18.72,14.47C18.58,14.61,18.5,14.8,18.5,15v3.5H15c-0.2,0-0.39,0.08-0.53,0.22L12,21.19 l-2.47-2.47C9.39,18.58,9.2,18.5,9,18.5H5.5V15c0-0.2-0.08-0.39-0.22-0.53L2.81,12l2.47-2.47C5.42,9.39,5.5,9.2,5.5,9V5.5H9 c0.2,0,0.39-0.08,0.53-0.22L12,2.81l2.47,2.47C14.61,5.42,14.8,5.5,15,5.5h3.5V9c0,0.2,0.08,0.39,0.22,0.53L21.19,12L18.72,14.47z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_location.xml
index 2d1de94..d437035 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_location.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_location.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,6c-1.88,0-3,1.04-3,3c0,1.91,1.06,3,3,3c1.89,0,3-1.05,3-3C15,7.08,13.93,6,12,6z M12,10.5 c-1.15,0.01-1.5-0.47-1.5-1.5c0-1.06,0.37-1.5,1.5-1.5c1.15-0.01,1.5,0.47,1.5,1.5C13.5,10.09,13.1,10.5,12,10.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M11.99,2C9.69,1.94,5,2.93,5,9c0,6.88,6.23,12.56,6.5,12.8c0.14,0.13,0.32,0.2,0.5,0.2s0.36-0.06,0.5-0.2 C12.77,21.56,19,15.88,19,9C19,2.87,14.3,1.96,11.99,2z M12,20.2C10.55,18.7,6.5,14.12,6.5,9c0-4.91,3.63-5.55,5.44-5.5 C16.9,3.34,17.5,7.14,17.5,9C17.5,14.13,13.45,18.7,12,20.2z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,6c-1.88,0-3,1.04-3,3c0,1.91,1.06,3,3,3c1.89,0,3-1.05,3-3C15,7.08,13.93,6,12,6z M12,10.5 c-1.15,0.01-1.5-0.47-1.5-1.5c0-1.06,0.37-1.5,1.5-1.5c1.15-0.01,1.5,0.47,1.5,1.5C13.5,10.09,13.1,10.5,12,10.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M11.99,2C9.69,1.94,5,2.93,5,9c0,6.88,6.23,12.56,6.5,12.8c0.14,0.13,0.32,0.2,0.5,0.2s0.36-0.06,0.5-0.2 C12.77,21.56,19,15.88,19,9C19,2.87,14.3,1.96,11.99,2z M12,20.2C10.55,18.7,6.5,14.12,6.5,9c0-4.91,3.63-5.55,5.44-5.5 C16.9,3.34,17.5,7.14,17.5,9C17.5,14.13,13.45,18.7,12,20.2z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_privacy.xml
index b8e5a7d..28d111d 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_privacy.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_privacy.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M22.74,11.4C20.87,7.33,16.77,4.5,12,4.5S3.13,7.33,1.26,11.4c-0.17,0.38-0.17,0.83,0,1.21c1.87,4.07,5.97,6.9,10.74,6.9 c0.68,0,1.35-0.06,2-0.18v-1.55C13.35,17.91,12.68,18,12,18c-4.02,0-7.7-2.36-9.38-5.98C4.3,8.36,7.98,6,12,6s7.7,2.36,9.38,5.98 c-0.08,0.17-0.19,0.33-0.28,0.5c0.47,0.22,0.9,0.51,1.27,0.85c0.13-0.24,0.25-0.48,0.37-0.73C22.92,12.22,22.92,11.78,22.74,11.4 z"/>
- <path android:fillColor="@android:color/white" android:pathData="M16.5,12c0-2.3-1.06-4.5-4.5-4.5c-3.43,0-4.5,2.22-4.5,4.5c0,2.3,1.06,4.5,4.5,4.5c0.83,0,1.52-0.14,2.09-0.36 c0.26-1.46,1.14-2.69,2.37-3.42C16.48,12.48,16.5,12.24,16.5,12z M12,15c-3.05,0.04-3-2.35-3-3c0-0.63-0.04-3.06,3-3 c3.05-0.04,3,2.35,3,3C15,12.63,15.04,15.06,12,15z"/>
- <path android:fillColor="@android:color/white" android:pathData="M21,17v-1c0-1.1-0.9-2-2-2s-2,0.9-2,2v1c-0.55,0-1,0.45-1,1v3c0,0.55,0.45,1,1,1h4c0.55,0,1-0.45,1-1v-3 C22,17.45,21.55,17,21,17z M18.5,16c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v1h-1V16z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M22.74,11.4C20.87,7.33,16.77,4.5,12,4.5S3.13,7.33,1.26,11.4c-0.17,0.38-0.17,0.83,0,1.21c1.87,4.07,5.97,6.9,10.74,6.9 c0.68,0,1.35-0.06,2-0.18v-1.55C13.35,17.91,12.68,18,12,18c-4.02,0-7.7-2.36-9.38-5.98C4.3,8.36,7.98,6,12,6s7.7,2.36,9.38,5.98 c-0.08,0.17-0.19,0.33-0.28,0.5c0.47,0.22,0.9,0.51,1.27,0.85c0.13-0.24,0.25-0.48,0.37-0.73C22.92,12.22,22.92,11.78,22.74,11.4 z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M16.5,12c0-2.3-1.06-4.5-4.5-4.5c-3.43,0-4.5,2.22-4.5,4.5c0,2.3,1.06,4.5,4.5,4.5c0.83,0,1.52-0.14,2.09-0.36 c0.26-1.46,1.14-2.69,2.37-3.42C16.48,12.48,16.5,12.24,16.5,12z M12,15c-3.05,0.04-3-2.35-3-3c0-0.63-0.04-3.06,3-3 c3.05-0.04,3,2.35,3,3C15,12.63,15.04,15.06,12,15z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M21,17v-1c0-1.1-0.9-2-2-2s-2,0.9-2,2v1c-0.55,0-1,0.45-1,1v3c0,0.55,0.45,1,1,1h4c0.55,0,1-0.45,1-1v-3 C22,17.45,21.55,17,21,17z M18.5,16c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v1h-1V16z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_security_white.xml
index 0475e33..7f654c1 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_security_white.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_security_white.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M18.5,1C17.03,0.96,14,1.62,14,5.5v2.49H6.25C5.01,7.99,4,9,4,10.24v9.51C4,20.99,5.01,22,6.25,22h11.5 c1.24,0,2.25-1.01,2.25-2.25v-9.51c0-1.24-1.01-2.25-2.25-2.25H15.5V5.5c0-2.77,2-3.01,3.05-3c1.02-0.02,2.96,0.28,2.96,3V6H23 V5.5C23,1.6,19.97,0.96,18.5,1z M17.75,9.49c0.41,0,0.75,0.34,0.75,0.75v9.51c0,0.41-0.34,0.75-0.75,0.75H6.25 c-0.41,0-0.75-0.34-0.75-0.75v-9.51c0-0.41,0.34-0.75,0.75-0.75H17.75z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12,17.74c0.13,0,2.75,0.06,2.75-2.75c0-2.34-1.85-2.77-2.74-2.75c-0.89-0.02-2.76,0.4-2.76,2.75 C9.25,17.41,11.19,17.74,12,17.74z M12.03,13.74c1.32-0.06,1.22,1.22,1.22,1.25c0,0.89-0.42,1.26-1.25,1.25 c-0.81,0.01-1.25-0.34-1.25-1.25C10.75,14.15,11.12,13.73,12.03,13.74z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M18.5,1C17.03,0.96,14,1.62,14,5.5v2.49H6.25C5.01,7.99,4,9,4,10.24v9.51C4,20.99,5.01,22,6.25,22h11.5 c1.24,0,2.25-1.01,2.25-2.25v-9.51c0-1.24-1.01-2.25-2.25-2.25H15.5V5.5c0-2.77,2-3.01,3.05-3c1.02-0.02,2.96,0.28,2.96,3V6H23 V5.5C23,1.6,19.97,0.96,18.5,1z M17.75,9.49c0.41,0,0.75,0.34,0.75,0.75v9.51c0,0.41-0.34,0.75-0.75,0.75H6.25 c-0.41,0-0.75-0.34-0.75-0.75v-9.51c0-0.41,0.34-0.75,0.75-0.75H17.75z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,17.74c0.13,0,2.75,0.06,2.75-2.75c0-2.34-1.85-2.77-2.74-2.75c-0.89-0.02-2.76,0.4-2.76,2.75 C9.25,17.41,11.19,17.74,12,17.74z M12.03,13.74c1.32-0.06,1.22,1.22,1.22,1.25c0,0.89-0.42,1.26-1.25,1.25 c-0.81,0.01-1.25-0.34-1.25-1.25C10.75,14.15,11.12,13.73,12.03,13.74z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
index 0c0a682..70d3628 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M 11.25 10 H 12.75 V 17 H 11.25 V 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 7 C 12.4142135624 7 12.75 7.33578643763 12.75 7.75 C 12.75 8.16421356237 12.4142135624 8.5 12 8.5 C 11.5857864376 8.5 11.25 8.16421356237 11.25 7.75 C 11.25 7.33578643763 11.5857864376 7 12 7 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12,2C4.41,2,2,6.9,2,12c0,5.09,2.35,10,10,10c7.59,0,10-4.9,10-10C22,6.91,19.65,2,12,2z M12,20.5 c-2.64,0.05-8.5-0.59-8.5-8.5c0-7.91,5.88-8.55,8.5-8.5c2.64-0.05,8.5,0.59,8.5,8.5C20.5,19.91,14.62,20.55,12,20.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 11.25 10 H 12.75 V 17 H 11.25 V 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 7 C 12.4142135624 7 12.75 7.33578643763 12.75 7.75 C 12.75 8.16421356237 12.4142135624 8.5 12 8.5 C 11.5857864376 8.5 11.25 8.16421356237 11.25 7.75 C 11.25 7.33578643763 11.5857864376 7 12 7 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,2C4.41,2,2,6.9,2,12c0,5.09,2.35,10,10,10c7.59,0,10-4.9,10-10C22,6.91,19.65,2,12,2z M12,20.5 c-2.64,0.05-8.5-0.59-8.5-8.5c0-7.91,5.88-8.55,8.5-8.5c2.64-0.05,8.5,0.59,8.5,8.5C20.5,19.91,14.62,20.55,12,20.5z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_wireless.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_wireless.xml
index 2899c7f..63346a4 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_wireless.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_settings_wireless.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:tint="?android:attr/colorControlNormal" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12.14,6c4.29,0.06,7.79,2.34,9.81,4.05l1.07-1.07c-2.26-1.94-6.06-4.41-10.86-4.48C8.32,4.46,4.57,5.96,1,9l1.07,1.07 C5.33,7.32,8.72,5.95,12.14,6z"/>
- <path android:fillColor="@android:color/white" android:pathData="M11.97,11.5c0.04,0,0.08,0,0.12,0c2.54,0.04,4.67,1.25,6.07,2.34l1.08-1.08c-1.6-1.28-4.07-2.71-7.13-2.76 c-2.54-0.03-4.99,0.91-7.33,2.78l1.07,1.07C7.84,12.3,9.89,11.5,11.97,11.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M11.98,17.5c0.02,0,0.04,0,0.05,0c0.73,0.01,1.38,0.24,1.93,0.53l1.1-1.1c-0.79-0.49-1.81-0.92-3.01-0.93 c-1.07-0.01-2.12,0.31-3.12,0.94l1.1,1.1C10.68,17.69,11.33,17.5,11.98,17.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12.14,6c4.29,0.06,7.79,2.34,9.81,4.05l1.07-1.07c-2.26-1.94-6.06-4.41-10.86-4.48C8.32,4.46,4.57,5.96,1,9l1.07,1.07 C5.33,7.32,8.72,5.95,12.14,6z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M11.97,11.5c0.04,0,0.08,0,0.12,0c2.54,0.04,4.67,1.25,6.07,2.34l1.08-1.08c-1.6-1.28-4.07-2.71-7.13-2.76 c-2.54-0.03-4.99,0.91-7.33,2.78l1.07,1.07C7.84,12.3,9.89,11.5,11.97,11.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M11.98,17.5c0.02,0,0.04,0,0.05,0c0.73,0.01,1.38,0.24,1.93,0.53l1.1-1.1c-0.79-0.49-1.81-0.92-3.01-0.93 c-1.07-0.01-2.12,0.31-3.12,0.94l1.1,1.1C10.68,17.69,11.33,17.5,11.98,17.5z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_storage_white.xml
index 7b5d946..0ef8a7c 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_storage_white.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_storage_white.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M20,4H4C3.45,4,3,4.45,3,5v2c0,0.55,0.45,1,1,1h16c0.55,0,1-0.45,1-1V5C21,4.45,20.55,4,20,4z M6,7C5.96,7,5,7.06,5,6 c0-1.06,0.97-1,1-1c0.04,0,1-0.06,1,1C7,7.06,6.03,7,6,7z"/>
- <path android:fillColor="@android:color/white" android:pathData="M20,10H4c-0.55,0-1,0.45-1,1v2c0,0.55,0.45,1,1,1h16c0.55,0,1-0.45,1-1v-2C21,10.45,20.55,10,20,10z M6,13 c-0.04,0-1,0.06-1-1c0-1.06,0.97-1,1-1c0.04,0,1-0.06,1,1C7,13.06,6.03,13,6,13z"/>
- <path android:fillColor="@android:color/white" android:pathData="M20,16H4c-0.55,0-1,0.45-1,1v2c0,0.55,0.45,1,1,1h16c0.55,0,1-0.45,1-1v-2C21,16.45,20.55,16,20,16z M6,19 c-0.04,0-1,0.06-1-1c0-1.06,0.97-1,1-1c0.04,0,1-0.06,1,1C7,19.06,6.03,19,6,19z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M20,4H4C3.45,4,3,4.45,3,5v2c0,0.55,0.45,1,1,1h16c0.55,0,1-0.45,1-1V5C21,4.45,20.55,4,20,4z M6,7C5.96,7,5,7.06,5,6 c0-1.06,0.97-1,1-1c0.04,0,1-0.06,1,1C7,7.06,6.03,7,6,7z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M20,10H4c-0.55,0-1,0.45-1,1v2c0,0.55,0.45,1,1,1h16c0.55,0,1-0.45,1-1v-2C21,10.45,20.55,10,20,10z M6,13 c-0.04,0-1,0.06-1-1c0-1.06,0.97-1,1-1c0.04,0,1-0.06,1,1C7,13.06,6.03,13,6,13z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M20,16H4c-0.55,0-1,0.45-1,1v2c0,0.55,0.45,1,1,1h16c0.55,0,1-0.45,1-1v-2C21,16.45,20.55,16,20,16z M6,19 c-0.04,0-1,0.06-1-1c0-1.06,0.97-1,1-1c0.04,0,1-0.06,1,1C7,19.06,6.03,19,6,19z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
index 019fed9..b9753f5 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
+++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M14,3.3v1.58c2.35,0.89,5.55,3.95,5.5,7.18c-0.06,3.65-3.79,6.41-5.5,7.05v1.58c1.12-0.33,6.92-3.18,7-8.61 C21.07,7.39,16.32,3.99,14,3.3z"/>
- <path android:fillColor="@android:color/white" android:pathData="M16.5,12.05c0.01-0.53-0.02-2.55-2.5-4.54v9C15.72,15.12,16.48,13.52,16.5,12.05z"/>
- <path android:fillColor="@android:color/white" android:pathData="M9.86,6.08L6.95,9H6c-2.56,0-3.02,2.02-3,2.99C2.97,12.96,3.44,15,6,15h0.95l2.91,2.92C10.69,18.75,12,18.1,12,17.04V6.96 C12,5.85,10.65,5.29,9.86,6.08z M10.5,16.43l-2.7-2.71c-0.14-0.14-0.33-0.22-0.53-0.22H6c-1.42,0-1.51-0.99-1.5-1.54 C4.47,10.73,5.29,10.5,6,10.5h1.26c0.2,0,0.39-0.08,0.53-0.22l2.7-2.71V16.43z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M14,3.3v1.58c2.35,0.89,5.55,3.95,5.5,7.18c-0.06,3.65-3.79,6.41-5.5,7.05v1.58c1.12-0.33,6.92-3.18,7-8.61 C21.07,7.39,16.32,3.99,14,3.3z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M16.5,12.05c0.01-0.53-0.02-2.55-2.5-4.54v9C15.72,15.12,16.48,13.52,16.5,12.05z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M9.86,6.08L6.95,9H6c-2.56,0-3.02,2.02-3,2.99C2.97,12.96,3.44,15,6,15h0.95l2.91,2.92C10.69,18.75,12,18.1,12,17.04V6.96 C12,5.85,10.65,5.29,9.86,6.08z M10.5,16.43l-2.7-2.71c-0.14-0.14-0.33-0.22-0.53-0.22H6c-1.42,0-1.51-0.99-1.5-1.54 C4.47,10.73,5.29,10.5,6,10.5h1.26c0.2,0,0.39-0.08,0.53-0.22l2.7-2.71V16.43z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_apps.xml
index fd71322..8db613d 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_apps.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_apps.xml
@@ -20,30 +20,30 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M6.5,4h-1C4.67,4,4,4.67,4,5.5v1C4,7.33,4.67,8,5.5,8h1C7.33,8,8,7.33,8,6.5v-1C8,4.67,7.33,4,6.5,4z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12.5,4h-1C10.67,4,10,4.67,10,5.5v1C10,7.33,10.67,8,11.5,8h1C13.33,8,14,7.33,14,6.5v-1C14,4.67,13.33,4,12.5,4z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M18.5,4h-1C16.67,4,16,4.67,16,5.5v1C16,7.33,16.67,8,17.5,8h1C19.33,8,20,7.33,20,6.5v-1C20,4.67,19.33,4,18.5,4z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M6.5,10h-1C4.67,10,4,10.67,4,11.5v1C4,13.33,4.67,14,5.5,14h1C7.33,14,8,13.33,8,12.5v-1C8,10.67,7.33,10,6.5,10z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12.5,10h-1c-0.83,0-1.5,0.67-1.5,1.5v1c0,0.83,0.67,1.5,1.5,1.5h1c0.83,0,1.5-0.67,1.5-1.5v-1C14,10.67,13.33,10,12.5,10 z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M18.5,10h-1c-0.83,0-1.5,0.67-1.5,1.5v1c0,0.83,0.67,1.5,1.5,1.5h1c0.83,0,1.5-0.67,1.5-1.5v-1C20,10.67,19.33,10,18.5,10 z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M6.5,16h-1C4.67,16,4,16.67,4,17.5v1C4,19.33,4.67,20,5.5,20h1C7.33,20,8,19.33,8,18.5v-1C8,16.67,7.33,16,6.5,16z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12.5,16h-1c-0.83,0-1.5,0.67-1.5,1.5v1c0,0.83,0.67,1.5,1.5,1.5h1c0.83,0,1.5-0.67,1.5-1.5v-1C14,16.67,13.33,16,12.5,16 z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M18.5,16h-1c-0.83,0-1.5,0.67-1.5,1.5v1c0,0.83,0.67,1.5,1.5,1.5h1c0.83,0,1.5-0.67,1.5-1.5v-1C20,16.67,19.33,16,18.5,16 z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml
index 463525d..1b4ec92 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -21,12 +21,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M5.25,18H3.5V5.5h17.75C21.66,5.5,22,5.16,22,4.75S21.66,4,21.25,4H3.5C2.67,4,2,4.67,2,5.5V18c0,0.83,0.67,1.5,1.5,1.5 h1.75C5.66,19.5,6,19.16,6,18.75S5.66,18,5.25,18z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M10.5,14.5C9.12,14.5,8,15.62,8,17s1.12,2.5,2.5,2.5S13,18.38,13,17S11.88,14.5,10.5,14.5z M10.5,18c-0.55,0-1-0.45-1-1 s0.45-1,1-1s1,0.45,1,1S11.05,18,10.5,18z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.5,8.5h-4C15.67,8.5,15,9.17,15,10v8c0,0.83,0.67,1.5,1.5,1.5h4c0.83,0,1.5-0.67,1.5-1.5v-8 C22,9.17,21.33,8.5,20.5,8.5z M20.5,18h-4v-8h4V18z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help.xml
index fce8140..d062e65 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,22c0,0,0.01,0,0.01,0c5.5,0,9.98-4.47,9.99-9.98V12c0-5.51-4.49-10-10-10S2,6.49,2,12S6.49,22,12,22z M12,3.5 c4.69,0,8.5,3.81,8.5,8.5v0.02c0,4.68-3.81,8.48-8.49,8.48c0,0-0.01,0-0.01,0c-4.69,0-8.5-3.81-8.5-8.5S7.31,3.5,12,3.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M8.67,9.98c0.4,0.1,0.81-0.15,0.9-0.56c0.11-0.47,0.33-0.86,0.65-1.19c0.94-0.94,2.59-0.94,3.54,0 c0.49,0.49,0.73,1.13,0.67,1.76c-0.06,0.57-0.36,1.06-0.84,1.38c-0.13,0.08-0.26,0.16-0.4,0.24c-0.7,0.4-1.67,0.94-1.93,2.51 c-0.07,0.41,0.21,0.8,0.61,0.86C11.92,15,11.96,15,12,15c0.36,0,0.68-0.26,0.74-0.62c0.15-0.87,0.58-1.12,1.19-1.46 c0.17-0.09,0.33-0.19,0.49-0.29c0.87-0.58,1.41-1.46,1.51-2.48c0.11-1.08-0.29-2.17-1.1-2.97c-1.51-1.51-4.15-1.51-5.66,0 c-0.52,0.51-0.88,1.17-1.05,1.9C8.02,9.48,8.27,9.88,8.67,9.98z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 16 C 12.5522847498 16 13 16.4477152502 13 17 C 13 17.5522847498 12.5522847498 18 12 18 C 11.4477152502 18 11 17.5522847498 11 17 C 11 16.4477152502 11.4477152502 16 12 16 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_phone_info.xml
index 0983f9f..f41f7a0 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_phone_info.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_phone_info.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M8,1C6.34,1,5,2.34,5,4v16c0,1.66,1.34,3,3,3h8c1.66,0,3-1.34,3-3V4c0-1.66-1.34-3-3-3H8z M16,21.5H8 c-0.83,0-1.5-0.67-1.5-1.5h11C17.5,20.83,16.83,21.5,16,21.5z M17.5,18.5h-11v-13h11V18.5z M17.5,4h-11c0-0.83,0.67-1.5,1.5-1.5h8 C16.83,2.5,17.5,3.17,17.5,4z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,10.5c-0.41,0-0.75,0.34-0.75,0.75v5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-5 C12.75,10.84,12.41,10.5,12,10.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accessibility.xml
index bfffc30..f17b5b9 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accessibility.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accessibility.xml
@@ -20,18 +20,18 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 0.5 C 13.1045694997 0.5 14 1.39543050034 14 2.5 C 14 3.60456949966 13.1045694997 4.5 12 4.5 C 10.8954305003 4.5 10 3.60456949966 10 2.5 C 10 1.39543050034 10.8954305003 0.5 12 0.5 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.72,5.28c-0.12-0.4-0.54-0.62-0.94-0.5C19.75,4.79,16.55,5.75,12,5.75c-4.53,0-7.75-0.96-7.78-0.97 c-0.39-0.12-0.81,0.1-0.94,0.5c-0.12,0.4,0.1,0.81,0.5,0.94C3.89,6.25,5.89,6.85,9,7.12v12.13C9,19.66,9.34,20,9.75,20 s0.75-0.34,0.75-0.75V14h3v5.25c0,0.41,0.34,0.75,0.75,0.75S15,19.66,15,19.25V7.12c3.11-0.27,5.11-0.87,5.22-0.9 C20.61,6.1,20.84,5.68,20.72,5.28z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accounts.xml
index f213bc4..f02da58 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accounts.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_accounts.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,6c-1.65,0-3,1.35-3,3v0.01C9,10.66,10.35,12,11.99,12c0,0,0,0,0.01,0c1.65,0,3-1.35,3-3S13.65,6,12,6z M12,10.5 C12,10.5,12,10.5,12,10.5c-0.83,0-1.5-0.67-1.5-1.49V9c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5S12.83,10.5,12,10.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M19.25,3.25H4.75c-0.83,0-1.5,0.67-1.5,1.5v14.5c0,0.83,0.67,1.5,1.5,1.5h14.5c0.83,0,1.5-0.67,1.5-1.5V4.75 C20.75,3.92,20.08,3.25,19.25,3.25z M16.5,19.25h-9v-3.5C7.5,15.34,7.84,15,8.25,15h7.5c0.41,0,0.75,0.34,0.75,0.75V19.25z M19.25,19.25H18v-3.5c0-1.24-1.01-2.25-2.25-2.25h-7.5C7.01,13.5,6,14.51,6,15.75v3.5H4.75V4.75h14.5L19.25,19.25z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_battery_white.xml
index 4ed698c..e27cb8d 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_battery_white.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_battery_white.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M13,2.49h-2c-0.55,0-1,0.45-1,1V4H7C6.45,4,6,4.45,6,5v16c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V5c0-0.55-0.45-1-1-1h-3 V3.49C14,2.94,13.55,2.49,13,2.49z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml
index 2e66268..19acd6a 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_display_white.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M21.25,11.25h-2.8A6.46,6.46,0,0,0,17.09,8l2-2A0.75 0.75 ,0,0,0,18,4.93l-2,2a6.46,6.46,0,0,0-3.28-1.36V2.75a0.75 0.75 ,0,0,0-1.5,0v2.8A6.46,6.46,0,0,0,8,6.91l-2-2A0.75 0.75 ,0,0,0,4.93,6l2,2a6.46,6.46,0,0,0-1.36,3.28H2.75a0.75 0.75 ,0,0,0,0,1.5h2.8A6.46,6.46,0,0,0,6.91,16l-2,2A0.75 0.75 ,0,0,0,6,19.07l2-2a6.46,6.46,0,0,0,3.28,1.36v2.8a0.75 0.75 ,0,0,0,1.5,0v-2.8A6.46,6.46,0,0,0,16,17.09l2,2A0.75 0.75 ,0,0,0,19.07,18l-2-2a6.46,6.46,0,0,0,1.36-3.28h2.8a0.75 0.75 ,0,0,0,0-1.5ZM12,17a5,5,0,1,1,5-5A5,5,0,0,1,12,17Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,15.5a3.5,3.5,0,0,0,0-7Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_location.xml
index a00c85f..762d67d 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_location.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_location.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,7c-1.66,0-3,1.34-3,3s1.34,3,3,3s3-1.34,3-3S13.66,7,12,7z M12,11.5c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5 s1.5,0.67,1.5,1.5S12.83,11.5,12,11.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,2.01c-4.5,0-8,3.49-8,8c0,5.49,5.48,10.24,7.37,11.76c0.19,0.15,0.41,0.22,0.63,0.22c0.22,0,0.44-0.07,0.62-0.22 C14.5,20.26,20,15.5,20,10C20,5.72,16.5,2.01,12,2.01z M12,20.34c-2.18-1.8-6.5-5.94-6.5-10.34c0-3.64,2.86-6.5,6.5-6.5 c3.58,0,6.5,2.91,6.5,6.49C18.5,14.4,14.19,18.53,12,20.34z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_privacy.xml
index 69cd1a4..12a82f2 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_privacy.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_privacy.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,8c-2.21,0-4,1.79-4,4s1.79,4,4,4c0.76,0,1.46-0.22,2.06-0.59c0.16-1.38,0.88-2.59,1.94-3.39c0-0.01,0-0.02,0-0.02 C16,9.79,14.21,8,12,8z M12,14.5c-1.38,0-2.5-1.12-2.5-2.5s1.12-2.5,2.5-2.5c1.38,0,2.5,1.12,2.5,2.5S13.38,14.5,12,14.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M3.09,12C3.73,10.81,6.43,6.5,12,6.5c4.53,0,7.14,2.79,8.31,4.5h1.77C21.1,9.28,18.05,5,12,5c-7.4,0-10.32,6.42-10.44,6.7 c-0.09,0.19-0.09,0.41,0,0.61C1.68,12.58,4.61,19,12,19c0.71,0,1.37-0.07,2-0.18V17.3c-0.62,0.13-1.28,0.2-2,0.2 C6.39,17.5,3.73,13.21,3.09,12z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M21,16c0-0.35,0-0.72,0-1c0-1.1-0.9-2-2-2c-1.1,0-2,0.9-2,2c0,0.37,0,0.7,0,1c-0.55,0-1,0.45-1,1v3c0,0.55,0.45,1,1,1h4 c0.55,0,1-0.45,1-1v-3C22,16.45,21.55,16,21,16z M20,16h-2v-1c0-0.55,0.45-1,1-1s1,0.45,1,1V16z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_security_white.xml
index c499596..e93e63f 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_security_white.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_security_white.xml
@@ -20,9 +20,9 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 13.5 C 12.8284271247 13.5 13.5 14.1715728753 13.5 15 C 13.5 15.8284271247 12.8284271247 16.5 12 16.5 C 11.1715728753 16.5 10.5 15.8284271247 10.5 15 C 10.5 14.1715728753 11.1715728753 13.5 12 13.5 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M18.51,1.46c-2.19-0.06-3.98,1.61-4.01,3.68V8.5h-9C4.67,8.5,4,9.17,4,10v10c0,0.83,0.67,1.5,1.5,1.5h13 c0.83,0,1.5-0.67,1.5-1.5V10c0-0.83-0.67-1.5-1.5-1.5H16V5.15c0.02-1.23,1.14-2.23,2.51-2.19C19.9,2.93,20.98,3.92,21,5.15 c0.01,0.41,0.36,0.71,0.76,0.74c0.41-0.01,0.74-0.35,0.74-0.76C22.46,3.07,20.7,1.39,18.51,1.46z M18.5,10v10h-13V10H18.5z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
index fe9c578..9ec3ffc 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M4.92,4.94c-3.9,3.91-3.9,10.24,0.01,14.14s10.24,3.9,14.14-0.01C20.95,17.2,22,14.65,22,12c0-2.65-1.06-5.19-2.93-7.07 C15.16,1.03,8.83,1.03,4.92,4.94z M18,18c-1.6,1.59-3.76,2.48-6.02,2.48c-4.69-0.01-8.49-3.83-8.48-8.52 c0.01-4.69,3.83-8.49,8.52-8.48c4.69,0.01,8.49,3.83,8.48,8.52C20.49,14.25,19.6,16.41,18,18z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 7 C 12.5522847498 7 13 7.44771525017 13 8 C 13 8.55228474983 12.5522847498 9 12 9 C 11.4477152502 9 11 8.55228474983 11 8 C 11 7.44771525017 11.4477152502 7 12 7 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,10.5c-0.41,0-0.75,0.34-0.75,0.75v5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-5 C12.75,10.84,12.41,10.5,12,10.5z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless.xml
index be66878..c8c8abc 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless.xml
@@ -21,15 +21,15 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M12,2.75C7.95,2.69,4.05,4.3,1.22,7.2C0.96,7.5,0.97,7.95,1.24,8.23C1.53,8.53,2,8.54,2.3,8.25c2.55-2.61,6.05-4.06,9.7-4 c3.65-0.06,7.17,1.4,9.72,4.02c0.28,0.27,0.73,0.28,1.03,0.01c0.31-0.28,0.33-0.75,0.05-1.06C19.96,4.32,16.06,2.69,12,2.75z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M15.78,14.82c0.05,0.06,0.1,0.11,0.17,0.15c0.34,0.23,0.81,0.14,1.04-0.21s0.14-0.81-0.21-1.04 c-2.64-2.64-6.91-2.64-9.55,0c-0.27,0.29-0.27,0.73,0,1.02c0.28,0.3,0.76,0.32,1.06,0.04h0.03c0,0,0,0,0.01-0.01 c2.05-2.05,5.37-2.04,7.42,0.01C15.75,14.8,15.76,14.81,15.78,14.82z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.03,11.79c0.3-0.29,0.3-0.77,0.01-1.06h-0.01c-2.12-2.18-5.01-3.44-8.04-3.5c-3.04,0.06-5.93,1.32-8.05,3.5 c-0.29,0.3-0.28,0.77,0.01,1.06c0.3,0.29,0.77,0.28,1.06-0.01c1.85-1.88,4.36-2.96,7-3c2.62,0.05,5.11,1.13,6.95,3 C19.25,12.07,19.73,12.08,20.03,11.79z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage_white.xml
index e80df4f..355ee3b 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage_white.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_storage_white.xml
@@ -20,21 +20,21 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.25,2H3.75C3.34,2,3,2.34,3,2.75v4.5C3,7.66,3.34,8,3.75,8h16.5C20.66,8,21,7.66,21,7.25v-4.5C21,2.34,20.66,2,20.25,2 z M19.5,6.5h-15v-3h15V6.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 5.25 4.25 H 6.75 V 5.75 H 5.25 V 4.25 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.25,9H3.75C3.34,9,3,9.34,3,9.75v4.5C3,14.66,3.34,15,3.75,15h16.5c0.41,0,0.75-0.34,0.75-0.75v-4.5 C21,9.34,20.66,9,20.25,9z M19.5,13.5h-15v-3h15V13.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 5.25 11.25 H 6.75 V 12.75 H 5.25 V 11.25 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M20.25,16H3.75C3.34,16,3,16.34,3,16.75v4.5C3,21.66,3.34,22,3.75,22h16.5c0.41,0,0.75-0.34,0.75-0.75v-4.5 C21,16.34,20.66,16,20.25,16z M19.5,20.5h-15v-3h15V20.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M 5.25 18.25 H 6.75 V 19.75 H 5.25 V 18.25 Z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
index 9370151..25f81b7 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
@@ -20,12 +20,12 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M5.69,16l5.03,5.03c0.14,0.14,0.34,0.22,0.53,0.22c0.1,0,0.19-0.02,0.29-0.06C11.82,21.08,12,20.8,12,20.5v-17 c0-0.3-0.18-0.58-0.46-0.69c-0.28-0.11-0.6-0.05-0.82,0.16L5.69,8H3.49C2.68,8.01,2.01,8.68,2,9.5v5C2,15.33,2.67,16,3.5,16H5.69z M3.5,9.5H6c0.2,0,0.39-0.08,0.53-0.22l3.97-3.97v13.38l-3.97-3.97C6.39,14.58,6.2,14.5,6,14.5H3.5V9.5z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M13.52,20.64c0.09,0.34,0.39,0.56,0.72,0.56c0.06,0,0.13-0.01,0.19-0.02c3.29-0.87,5.88-3.46,6.75-6.75 c1.34-5.06-1.69-10.26-6.75-11.59c-0.4-0.11-0.81,0.13-0.92,0.53c-0.11,0.4,0.13,0.81,0.53,0.92c4.26,1.13,6.8,5.5,5.68,9.76 c-0.73,2.77-2.91,4.95-5.68,5.68C13.66,19.83,13.42,20.24,13.52,20.64z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="?android:attr/colorPrimary"
android:pathData="M13.85,14.96c-0.35,0.22-0.46,0.68-0.24,1.03c0.14,0.23,0.39,0.35,0.64,0.35c0.14,0,0.27-0.04,0.4-0.11 c1.13-0.7,1.92-1.81,2.22-3.1c0.3-1.3,0.08-2.64-0.62-3.77c-0.4-0.65-0.96-1.2-1.6-1.6C14.29,7.54,13.83,7.65,13.61,8 c-0.22,0.35-0.11,0.81,0.24,1.03c0.45,0.28,0.84,0.67,1.12,1.12c0.49,0.79,0.65,1.73,0.44,2.64C15.2,13.7,14.65,14.47,13.85,14.96z" />
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_apps.xml
index ff34995..69835c0 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_apps.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_apps.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M 6 10 C 7.10456949966 10 8 10.8954305003 8 12 C 8 13.1045694997 7.10456949966 14 6 14 C 4.89543050034 14 4 13.1045694997 4 12 C 4 10.8954305003 4.89543050034 10 6 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 6 4 C 7.10456949966 4 8 4.89543050034 8 6 C 8 7.10456949966 7.10456949966 8 6 8 C 4.89543050034 8 4 7.10456949966 4 6 C 4 4.89543050034 4.89543050034 4 6 4 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 18 4 C 19.1045694997 4 20 4.89543050034 20 6 C 20 7.10456949966 19.1045694997 8 18 8 C 16.8954305003 8 16 7.10456949966 16 6 C 16 4.89543050034 16.8954305003 4 18 4 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 6 16 C 7.10456949966 16 8 16.8954305003 8 18 C 8 19.1045694997 7.10456949966 20 6 20 C 4.89543050034 20 4 19.1045694997 4 18 C 4 16.8954305003 4.89543050034 16 6 16 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 16 C 13.1045694997 16 14 16.8954305003 14 18 C 14 19.1045694997 13.1045694997 20 12 20 C 10.8954305003 20 10 19.1045694997 10 18 C 10 16.8954305003 10.8954305003 16 12 16 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 18 10 C 19.1045694997 10 20 10.8954305003 20 12 C 20 13.1045694997 19.1045694997 14 18 14 C 16.8954305003 14 16 13.1045694997 16 12 C 16 10.8954305003 16.8954305003 10 18 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 18 16 C 19.1045694997 16 20 16.8954305003 20 18 C 20 19.1045694997 19.1045694997 20 18 20 C 16.8954305003 20 16 19.1045694997 16 18 C 16 16.8954305003 16.8954305003 16 18 16 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 10 C 13.1045694997 10 14 10.8954305003 14 12 C 14 13.1045694997 13.1045694997 14 12 14 C 10.8954305003 14 10 13.1045694997 10 12 C 10 10.8954305003 10.8954305003 10 12 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 4 C 13.1045694997 4 14 4.89543050034 14 6 C 14 7.10456949966 13.1045694997 8 12 8 C 10.8954305003 8 10 7.10456949966 10 6 C 10 4.89543050034 10.8954305003 4 12 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 6 10 C 7.10456949966 10 8 10.8954305003 8 12 C 8 13.1045694997 7.10456949966 14 6 14 C 4.89543050034 14 4 13.1045694997 4 12 C 4 10.8954305003 4.89543050034 10 6 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 6 4 C 7.10456949966 4 8 4.89543050034 8 6 C 8 7.10456949966 7.10456949966 8 6 8 C 4.89543050034 8 4 7.10456949966 4 6 C 4 4.89543050034 4.89543050034 4 6 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 18 4 C 19.1045694997 4 20 4.89543050034 20 6 C 20 7.10456949966 19.1045694997 8 18 8 C 16.8954305003 8 16 7.10456949966 16 6 C 16 4.89543050034 16.8954305003 4 18 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 6 16 C 7.10456949966 16 8 16.8954305003 8 18 C 8 19.1045694997 7.10456949966 20 6 20 C 4.89543050034 20 4 19.1045694997 4 18 C 4 16.8954305003 4.89543050034 16 6 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 16 C 13.1045694997 16 14 16.8954305003 14 18 C 14 19.1045694997 13.1045694997 20 12 20 C 10.8954305003 20 10 19.1045694997 10 18 C 10 16.8954305003 10.8954305003 16 12 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 18 10 C 19.1045694997 10 20 10.8954305003 20 12 C 20 13.1045694997 19.1045694997 14 18 14 C 16.8954305003 14 16 13.1045694997 16 12 C 16 10.8954305003 16.8954305003 10 18 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 18 16 C 19.1045694997 16 20 16.8954305003 20 18 C 20 19.1045694997 19.1045694997 20 18 20 C 16.8954305003 20 16 19.1045694997 16 18 C 16 16.8954305003 16.8954305003 16 18 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 10 C 13.1045694997 10 14 10.8954305003 14 12 C 14 13.1045694997 13.1045694997 14 12 14 C 10.8954305003 14 10 13.1045694997 10 12 C 10 10.8954305003 10.8954305003 10 12 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 4 C 13.1045694997 4 14 4.89543050034 14 6 C 14 7.10456949966 13.1045694997 8 12 8 C 10.8954305003 8 10 7.10456949966 10 6 C 10 4.89543050034 10.8954305003 4 12 4 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_devices_other.xml
index 733fe7f..c692eeb 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<vector android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M3,7c0-0.55,0.45-1,1-1h16c0.55,0,1-0.45,1-1v0c0-0.55-0.45-1-1-1H4C2.35,4,1,5.35,1,7v10c0,1.65,1.35,3,3,3h2 c0.55,0,1-0.45,1-1v0c0-0.55-0.45-1-1-1H4c-0.55,0-1-0.45-1-1V7z M12,12h-2c-0.55,0-1,0.45-1,1v0.78C8.39,14.33,8,15.11,8,16 c0,0.89,0.39,1.67,1,2.22V19c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1v-0.78c0.61-0.55,1-1.34,1-2.22c0-0.88-0.39-1.67-1-2.22V13 C13,12.45,12.55,12,12,12z M11,17.5c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5S11.83,17.5,11,17.5 M17,8 c-1.1,0-2,0.9-2,2v8c0,1.1,0.9,2,2,2h4c1.1,0,2-0.9,2-2v-8c0-1.1-0.9-2-2-2H17z M21,18h-4v-8h4V18z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M3,7c0-0.55,0.45-1,1-1h16c0.55,0,1-0.45,1-1v0c0-0.55-0.45-1-1-1H4C2.35,4,1,5.35,1,7v10c0,1.65,1.35,3,3,3h2 c0.55,0,1-0.45,1-1v0c0-0.55-0.45-1-1-1H4c-0.55,0-1-0.45-1-1V7z M12,12h-2c-0.55,0-1,0.45-1,1v0.78C8.39,14.33,8,15.11,8,16 c0,0.89,0.39,1.67,1,2.22V19c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1v-0.78c0.61-0.55,1-1.34,1-2.22c0-0.88-0.39-1.67-1-2.22V13 C13,12.45,12.55,12,12,12z M11,17.5c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5S11.83,17.5,11,17.5 M17,8 c-1.1,0-2,0.9-2,2v8c0,1.1,0.9,2,2,2h4c1.1,0,2-0.9,2-2v-8c0-1.1-0.9-2-2-2H17z M21,18h-4v-8h4V18z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_help.xml
index 4650a72..5a8185a 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_help.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_help.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M12,18c-0.55,0-1-0.45-1-1 c0-0.55,0.45-1,1-1s1,0.45,1,1C13,17.55,12.55,18,12,18z M13.1,14.32C12.98,14.71,12.65,15,12.24,15h-0.15 c-0.62,0-1.11-0.6-0.93-1.2c0.61-1.97,2.71-2.08,2.83-3.66c0.07-0.97-0.62-1.9-1.57-2.1c-1.04-0.22-1.98,0.39-2.3,1.28 C9.98,9.71,9.65,10,9.24,10H9.07C8.45,10,8,9.4,8.18,8.81C8.68,7.18,10.2,6,12,6c2.21,0,4,1.79,4,4 C16,12.22,13.63,12.67,13.1,14.32z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M12,18c-0.55,0-1-0.45-1-1 c0-0.55,0.45-1,1-1s1,0.45,1,1C13,17.55,12.55,18,12,18z M13.1,14.32C12.98,14.71,12.65,15,12.24,15h-0.15 c-0.62,0-1.11-0.6-0.93-1.2c0.61-1.97,2.71-2.08,2.83-3.66c0.07-0.97-0.62-1.9-1.57-2.1c-1.04-0.22-1.98,0.39-2.3,1.28 C9.98,9.71,9.65,10,9.24,10H9.07C8.45,10,8,9.4,8.18,8.81C8.68,7.18,10.2,6,12,6c2.21,0,4,1.79,4,4 C16,12.22,13.63,12.67,13.1,14.32z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_phone_info.xml
index dac1dee..54336d0 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_phone_info.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_phone_info.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,11L12,11c0.55,0,1,0.45,1,1v4c0,0.55-0.45,1-1,1c-0.55,0-1-0.45-1-1v-4C11,11.45,11.45,11,12,11"/>
- <path android:fillColor="@android:color/white" android:pathData="M16,1H8C6.34,1,5,2.34,5,4v16c0,1.65,1.35,3,3,3h8c1.65,0,3-1.35,3-3V4C19,2.34,17.66,1,16,1 M17,18H7V6h10V18z"/>
- <path android:fillColor="@android:color/white" android:pathData="M13,8c0,0.55-0.45,1-1,1c-0.55,0-1-0.45-1-1c0-0.55,0.45-1,1-1C12.55,7,13,7.45,13,8"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,11L12,11c0.55,0,1,0.45,1,1v4c0,0.55-0.45,1-1,1c-0.55,0-1-0.45-1-1v-4C11,11.45,11.45,11,12,11"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M16,1H8C6.34,1,5,2.34,5,4v16c0,1.65,1.35,3,3,3h8c1.65,0,3-1.35,3-3V4C19,2.34,17.66,1,16,1 M17,18H7V6h10V18z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M13,8c0,0.55-0.45,1-1,1c-0.55,0-1-0.45-1-1c0-0.55,0.45-1,1-1C12.55,7,13,7.45,13,8"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_accessibility.xml
index 3be42b3..4a4baf9 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_accessibility.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_accessibility.xml
@@ -14,9 +14,9 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M20.75,4.99c-0.14-0.55-0.69-0.87-1.24-0.75C17.13,4.77,14.48,5,12,5S6.87,4.77,4.49,4.24c-0.55-0.12-1.1,0.2-1.24,0.75 c-0.14,0.56,0.2,1.13,0.75,1.26C5.61,6.61,7.35,6.86,9,7v12c0,0.55,0.45,1,1,1s1-0.45,1-1v-4c0-0.55,0.45-1,1-1s1,0.45,1,1v4 c0,0.55,0.45,1,1,1s1-0.45,1-1V7c1.65-0.14,3.39-0.39,4.99-0.75C20.55,6.12,20.89,5.55,20.75,4.99z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 0 C 13.1045694997 0 14 0.895430500338 14 2 C 14 3.10456949966 13.1045694997 4 12 4 C 10.8954305003 4 10 3.10456949966 10 2 C 10 0.895430500338 10.8954305003 0 12 0 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M20.75,4.99c-0.14-0.55-0.69-0.87-1.24-0.75C17.13,4.77,14.48,5,12,5S6.87,4.77,4.49,4.24c-0.55-0.12-1.1,0.2-1.24,0.75 c-0.14,0.56,0.2,1.13,0.75,1.26C5.61,6.61,7.35,6.86,9,7v12c0,0.55,0.45,1,1,1s1-0.45,1-1v-4c0-0.55,0.45-1,1-1s1,0.45,1,1v4 c0,0.55,0.45,1,1,1s1-0.45,1-1V7c1.65-0.14,3.39-0.39,4.99-0.75C20.55,6.12,20.89,5.55,20.75,4.99z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 0 C 13.1045694997 0 14 0.895430500338 14 2 C 14 3.10456949966 13.1045694997 4 12 4 C 10.8954305003 4 10 3.10456949966 10 2 C 10 0.895430500338 10.8954305003 0 12 0 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 8 22 C 8.55228474983 22 9 22.4477152502 9 23 C 9 23.5522847498 8.55228474983 24 8 24 C 7.44771525017 24 7 23.5522847498 7 23 C 7 22.4477152502 7.44771525017 22 8 22 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 22 C 12.5522847498 22 13 22.4477152502 13 23 C 13 23.5522847498 12.5522847498 24 12 24 C 11.4477152502 24 11 23.5522847498 11 23 C 11 22.4477152502 11.4477152502 22 12 22 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 16 22 C 16.5522847498 22 17 22.4477152502 17 23 C 17 23.5522847498 16.5522847498 24 16 24 C 15.4477152502 24 15 23.5522847498 15 23 C 15 22.4477152502 15.4477152502 22 16 22 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_accounts.xml
index a9bf036..334b2b7 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_accounts.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_accounts.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M6,3C4.34,3,3,4.34,3,6v12c0,1.66,1.34,3,3,3h12c1.65,0,3-1.35,3-3V6c0-1.66-1.34-3-3-3H6z M19,6v9.79 C16.52,14.37,13.23,14,12,14s-4.52,0.37-7,1.79V6c0-0.55,0.45-1,1-1h12C18.55,5,19,5.45,19,6z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12,13c1.94,0,3.5-1.56,3.5-3.5S13.94,6,12,6S8.5,7.56,8.5,9.5S10.06,13,12,13"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M6,3C4.34,3,3,4.34,3,6v12c0,1.66,1.34,3,3,3h12c1.65,0,3-1.35,3-3V6c0-1.66-1.34-3-3-3H6z M19,6v9.79 C16.52,14.37,13.23,14,12,14s-4.52,0.37-7,1.79V6c0-0.55,0.45-1,1-1h12C18.55,5,19,5.45,19,6z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,13c1.94,0,3.5-1.56,3.5-3.5S13.94,6,12,6S8.5,7.56,8.5,9.5S10.06,13,12,13"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_battery_white.xml
index d616ad6..fff56ce 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_battery_white.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_battery_white.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M15,4h-1c0-1.1-0.9-2-2-2s-2,0.9-2,2H9C7.35,4,6,5.35,6,7v12c0,1.65,1.35,3,3,3h6c1.65,0,3-1.35,3-3V7 C18,5.35,16.65,4,15,4z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M15,4h-1c0-1.1-0.9-2-2-2s-2,0.9-2,2H9C7.35,4,6,5.35,6,7v12c0,1.65,1.35,3,3,3h6c1.65,0,3-1.35,3-3V7 C18,5.35,16.65,4,15,4z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_display_white.xml
index cf4af6f..723c36c 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_display_white.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_display_white.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M13.25,7.16C12.62,6.99,12,7.48,12,8.13v7.74c0,0.65,0.62,1.14,1.25,0.97C15.41,16.29,17,14.33,17,12 S15.41,7.71,13.25,7.16z"/>
- <path android:fillColor="@android:color/white" android:pathData="M21.19,9.88l-0.9-0.9C20.1,8.8,20,8.54,20,8.28V7c0-1.66-1.34-3-3-3h-1.28c-0.27,0-0.52-0.11-0.71-0.29l-0.9-0.9 c-1.17-1.17-3.07-1.17-4.24,0l-0.9,0.9C8.79,3.89,8.54,4,8.28,4H7C5.34,4,4,5.34,4,7v1.28C4,8.54,3.89,8.8,3.71,8.98l-0.9,0.9 c-1.17,1.17-1.17,3.07,0,4.24l0.9,0.9C3.89,15.2,4,15.46,4,15.72V17c0,1.66,1.34,3,3,3h1.28c0.27,0,0.52,0.11,0.71,0.29l0.9,0.9 c1.17,1.17,3.07,1.17,4.24,0l0.9-0.9C15.2,20.11,15.46,20,15.72,20H17c1.66,0,3-1.34,3-3v-1.28c0-0.27,0.11-0.52,0.29-0.71 l0.9-0.9C22.36,12.95,22.36,11.05,21.19,9.88z M19.77,12.71l-1.48,1.48C18.11,14.37,18,14.63,18,14.89V17c0,0.55-0.45,1-1,1h-2.11 c-0.27,0-0.52,0.11-0.71,0.29l-1.48,1.48c-0.39,0.39-1.02,0.39-1.41,0l-1.48-1.48C9.63,18.1,9.37,18,9.11,18H7c-0.55,0-1-0.45-1-1 v-2.1c0-0.27-0.11-0.52-0.29-0.71l-1.48-1.48c-0.39-0.39-0.39-1.02,0-1.41l1.48-1.48C5.9,9.63,6,9.37,6,9.11V7c0-0.55,0.45-1,1-1 h2.11c0.27,0,0.52-0.11,0.71-0.29l1.48-1.48c0.39-0.39,1.02-0.39,1.41,0l1.48,1.48C14.38,5.89,14.63,6,14.89,6H17 c0.55,0,1,0.45,1,1v2.11c0,0.27,0.11,0.52,0.29,0.71l1.48,1.48C20.16,11.68,20.16,12.32,19.77,12.71z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M13.25,7.16C12.62,6.99,12,7.48,12,8.13v7.74c0,0.65,0.62,1.14,1.25,0.97C15.41,16.29,17,14.33,17,12 S15.41,7.71,13.25,7.16z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M21.19,9.88l-0.9-0.9C20.1,8.8,20,8.54,20,8.28V7c0-1.66-1.34-3-3-3h-1.28c-0.27,0-0.52-0.11-0.71-0.29l-0.9-0.9 c-1.17-1.17-3.07-1.17-4.24,0l-0.9,0.9C8.79,3.89,8.54,4,8.28,4H7C5.34,4,4,5.34,4,7v1.28C4,8.54,3.89,8.8,3.71,8.98l-0.9,0.9 c-1.17,1.17-1.17,3.07,0,4.24l0.9,0.9C3.89,15.2,4,15.46,4,15.72V17c0,1.66,1.34,3,3,3h1.28c0.27,0,0.52,0.11,0.71,0.29l0.9,0.9 c1.17,1.17,3.07,1.17,4.24,0l0.9-0.9C15.2,20.11,15.46,20,15.72,20H17c1.66,0,3-1.34,3-3v-1.28c0-0.27,0.11-0.52,0.29-0.71 l0.9-0.9C22.36,12.95,22.36,11.05,21.19,9.88z M19.77,12.71l-1.48,1.48C18.11,14.37,18,14.63,18,14.89V17c0,0.55-0.45,1-1,1h-2.11 c-0.27,0-0.52,0.11-0.71,0.29l-1.48,1.48c-0.39,0.39-1.02,0.39-1.41,0l-1.48-1.48C9.63,18.1,9.37,18,9.11,18H7c-0.55,0-1-0.45-1-1 v-2.1c0-0.27-0.11-0.52-0.29-0.71l-1.48-1.48c-0.39-0.39-0.39-1.02,0-1.41l1.48-1.48C5.9,9.63,6,9.37,6,9.11V7c0-0.55,0.45-1,1-1 h2.11c0.27,0,0.52-0.11,0.71-0.29l1.48-1.48c0.39-0.39,1.02-0.39,1.41,0l1.48,1.48C14.38,5.89,14.63,6,14.89,6H17 c0.55,0,1,0.45,1,1v2.11c0,0.27,0.11,0.52,0.29,0.71l1.48,1.48C20.16,11.68,20.16,12.32,19.77,12.71z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_location.xml
index a802bee..9230e3e 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_location.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_location.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,3c-3.87,0-7,3.13-7,7c0,3.18,2.56,7.05,4.59,9.78c1.2,1.62,3.62,1.62,4.82,0C16.44,17.05,19,13.18,19,10 C19,6.13,15.87,3,12,3 M12,12.5c-1.38,0-2.5-1.12-2.5-2.5s1.12-2.5,2.5-2.5s2.5,1.12,2.5,2.5S13.38,12.5,12,12.5"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,3c-3.87,0-7,3.13-7,7c0,3.18,2.56,7.05,4.59,9.78c1.2,1.62,3.62,1.62,4.82,0C16.44,17.05,19,13.18,19,10 C19,6.13,15.87,3,12,3 M12,12.5c-1.38,0-2.5-1.12-2.5-2.5s1.12-2.5,2.5-2.5s2.5,1.12,2.5,2.5S13.38,12.5,12,12.5"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_privacy.xml
index 10c059f..4392c12 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_privacy.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_privacy.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M14.14,15.43C13.5,15.78,12.78,16,12,16c-2.48,0-4.5-2.02-4.5-4.5C7.5,9.02,9.52,7,12,7c2.48,0,4.5,2.02,4.5,4.5 c0,0.37-0.06,0.72-0.14,1.07C17,12.22,17.72,12,18.5,12c1.38,0,2.59,0.63,3.42,1.6c0.15-0.23,0.29-0.46,0.42-0.69 c0.48-0.87,0.48-1.95,0-2.81C20.32,6.46,16.45,4,12,4C7.55,4,3.68,6.46,1.66,10.09c-0.48,0.87-0.48,1.95,0,2.81 C3.68,16.54,7.55,19,12,19c0.68,0,1.35-0.06,2-0.18V16.5C14,16.13,14.06,15.78,14.14,15.43z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 8.8 C 13.4911688245 8.8 14.7 10.0088311755 14.7 11.5 C 14.7 12.9911688245 13.4911688245 14.2 12 14.2 C 10.5088311755 14.2 9.3 12.9911688245 9.3 11.5 C 9.3 10.0088311755 10.5088311755 8.8 12 8.8 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M21,17v-1c0-1.1-0.9-2-2-2s-2,0.9-2,2v1c-0.55,0-1,0.45-1,1v3c0,0.55,0.45,1,1,1h4c0.55,0,1-0.45,1-1v-3 C22,17.45,21.55,17,21,17z M18.5,16c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v1h-1V16z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M14.14,15.43C13.5,15.78,12.78,16,12,16c-2.48,0-4.5-2.02-4.5-4.5C7.5,9.02,9.52,7,12,7c2.48,0,4.5,2.02,4.5,4.5 c0,0.37-0.06,0.72-0.14,1.07C17,12.22,17.72,12,18.5,12c1.38,0,2.59,0.63,3.42,1.6c0.15-0.23,0.29-0.46,0.42-0.69 c0.48-0.87,0.48-1.95,0-2.81C20.32,6.46,16.45,4,12,4C7.55,4,3.68,6.46,1.66,10.09c-0.48,0.87-0.48,1.95,0,2.81 C3.68,16.54,7.55,19,12,19c0.68,0,1.35-0.06,2-0.18V16.5C14,16.13,14.06,15.78,14.14,15.43z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 8.8 C 13.4911688245 8.8 14.7 10.0088311755 14.7 11.5 C 14.7 12.9911688245 13.4911688245 14.2 12 14.2 C 10.5088311755 14.2 9.3 12.9911688245 9.3 11.5 C 9.3 10.0088311755 10.5088311755 8.8 12 8.8 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M21,17v-1c0-1.1-0.9-2-2-2s-2,0.9-2,2v1c-0.55,0-1,0.45-1,1v3c0,0.55,0.45,1,1,1h4c0.55,0,1-0.45,1-1v-3 C22,17.45,21.55,17,21,17z M18.5,16c0-0.28,0.22-0.5,0.5-0.5s0.5,0.22,0.5,0.5v1h-1V16z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_security_white.xml
index 8ca2dd6..baa6a0a 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_security_white.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_security_white.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M18.5,1C16.01,1,14,3.01,14,5.5V8H7c-1.65,0-3,1.35-3,3v8c0,1.65,1.35,3,3,3h10c1.65,0,3-1.35,3-3v-8c0-1.65-1.35-3-3-3h-1 V5.64c0-1.31,0.94-2.5,2.24-2.63c0.52-0.05,2.3,0.02,2.69,2.12C21.02,5.63,21.42,6,21.92,6c0.6,0,1.09-0.53,0.99-1.13 C22.47,2.3,20.55,1,18.5,1z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S13.1,17,12,17z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M18.5,1C16.01,1,14,3.01,14,5.5V8H7c-1.65,0-3,1.35-3,3v8c0,1.65,1.35,3,3,3h10c1.65,0,3-1.35,3-3v-8c0-1.65-1.35-3-3-3h-1 V5.64c0-1.31,0.94-2.5,2.24-2.63c0.52-0.05,2.3,0.02,2.69,2.12C21.02,5.63,21.42,6,21.92,6c0.6,0,1.09-0.53,0.99-1.13 C22.47,2.3,20.55,1,18.5,1z M12,17c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2S13.1,17,12,17z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
index 437afcc..54aa6ce 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M13,16c0,0.55-0.45,1-1,1s-1-0.45-1-1 v-4c0-0.55,0.45-1,1-1s1,0.45,1,1V16z M12,9c-0.55,0-1-0.45-1-1c0-0.55,0.45-1,1-1s1,0.45,1,1C13,8.55,12.55,9,12,9z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M13,16c0,0.55-0.45,1-1,1s-1-0.45-1-1 v-4c0-0.55,0.45-1,1-1s1,0.45,1,1V16z M12,9c-0.55,0-1-0.45-1-1c0-0.55,0.45-1,1-1s1,0.45,1,1C13,8.55,12.55,9,12,9z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_wireless.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_wireless.xml
index 145886a..c40f314 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_wireless.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_settings_wireless.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:tint="?android:attr/colorControlNormal" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M17.79,11.97c-3.7-2.67-8.4-2.29-11.58,0c-0.69,0.5-0.73,1.51-0.13,2.11l0.01,0.01c0.49,0.49,1.26,0.54,1.83,0.13 c2.6-1.84,5.88-1.61,8.16,0c0.57,0.4,1.34,0.36,1.83-0.13l0.01-0.01C18.52,13.48,18.48,12.47,17.79,11.97z"/>
- <path android:fillColor="@android:color/white" android:pathData="M21.84,7.95c-5.71-4.68-13.97-4.67-19.69,0c-0.65,0.53-0.69,1.51-0.1,2.1c0.51,0.51,1.33,0.55,1.89,0.09 c3.45-2.83,10.36-4.72,16.11,0c0.56,0.46,1.38,0.42,1.89-0.09C22.54,9.46,22.49,8.48,21.84,7.95z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 15 C 13.1045694997 15 14 15.8954305003 14 17 C 14 18.1045694997 13.1045694997 19 12 19 C 10.8954305003 19 10 18.1045694997 10 17 C 10 15.8954305003 10.8954305003 15 12 15 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M17.79,11.97c-3.7-2.67-8.4-2.29-11.58,0c-0.69,0.5-0.73,1.51-0.13,2.11l0.01,0.01c0.49,0.49,1.26,0.54,1.83,0.13 c2.6-1.84,5.88-1.61,8.16,0c0.57,0.4,1.34,0.36,1.83-0.13l0.01-0.01C18.52,13.48,18.48,12.47,17.79,11.97z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M21.84,7.95c-5.71-4.68-13.97-4.67-19.69,0c-0.65,0.53-0.69,1.51-0.1,2.1c0.51,0.51,1.33,0.55,1.89,0.09 c3.45-2.83,10.36-4.72,16.11,0c0.56,0.46,1.38,0.42,1.89-0.09C22.54,9.46,22.49,8.48,21.84,7.95z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 15 C 13.1045694997 15 14 15.8954305003 14 17 C 14 18.1045694997 13.1045694997 19 12 19 C 10.8954305003 19 10 18.1045694997 10 17 C 10 15.8954305003 10.8954305003 15 12 15 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_storage_white.xml
index 3ed5150..2ae828d 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_storage_white.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_storage_white.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M19,16H5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2C21,16.9,20.1,16,19,16z M6,19c-0.55,0-1-0.45-1-1 c0-0.55,0.45-1,1-1s1,0.45,1,1C7,18.55,6.55,19,6,19z"/>
- <path android:fillColor="@android:color/white" android:pathData="M5,8h14c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2H5C3.9,4,3,4.9,3,6C3,7.1,3.9,8,5,8z M6,5c0.55,0,1,0.45,1,1c0,0.55-0.45,1-1,1 S5,6.55,5,6C5,5.45,5.45,5,6,5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M19,10H5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2C21,10.9,20.1,10,19,10z M6,13c-0.55,0-1-0.45-1-1 c0-0.55,0.45-1,1-1s1,0.45,1,1C7,12.55,6.55,13,6,13z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M19,16H5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2C21,16.9,20.1,16,19,16z M6,19c-0.55,0-1-0.45-1-1 c0-0.55,0.45-1,1-1s1,0.45,1,1C7,18.55,6.55,19,6,19z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M5,8h14c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2H5C3.9,4,3,4.9,3,6C3,7.1,3.9,8,5,8z M6,5c0.55,0,1,0.45,1,1c0,0.55-0.45,1-1,1 S5,6.55,5,6C5,5.45,5.45,5,6,5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M19,10H5c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2C21,10.9,20.1,10,19,10z M6,13c-0.55,0-1-0.45-1-1 c0-0.55,0.45-1,1-1s1,0.45,1,1C7,12.55,6.55,13,6,13z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
index 0a9a4c7..4fc2489 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
+++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M10.29,5.71L7,9H6c-1.66,0-3,1.34-3,3s1.34,3,3,3h1l3.29,3.29c0.63,0.63,1.71,0.18,1.71-0.71V6.41 C12,5.52,10.92,5.08,10.29,5.71z"/>
- <path android:fillColor="@android:color/white" android:pathData="M14.79,15.52c1.04-0.82,1.71-2.09,1.71-3.52c0-1.43-0.67-2.7-1.71-3.52C14.47,8.22,14,8.47,14,8.88v6.23 C14,15.52,14.47,15.77,14.79,15.52z"/>
- <path android:fillColor="@android:color/white" android:pathData="M15.36,3.65C14.71,3.39,14,3.89,14,4.59v0c0,0.41,0.25,0.77,0.62,0.92C17.19,6.55,19,9.06,19,12 c0,2.94-1.81,5.45-4.38,6.49C14.25,18.64,14,19.01,14,19.41v0c0,0.7,0.71,1.19,1.36,0.93C18.67,19.02,21,15.78,21,12 C21,8.22,18.67,4.98,15.36,3.65z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M10.29,5.71L7,9H6c-1.66,0-3,1.34-3,3s1.34,3,3,3h1l3.29,3.29c0.63,0.63,1.71,0.18,1.71-0.71V6.41 C12,5.52,10.92,5.08,10.29,5.71z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M14.79,15.52c1.04-0.82,1.71-2.09,1.71-3.52c0-1.43-0.67-2.7-1.71-3.52C14.47,8.22,14,8.47,14,8.88v6.23 C14,15.52,14.47,15.77,14.79,15.52z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M15.36,3.65C14.71,3.39,14,3.89,14,4.59v0c0,0.41,0.25,0.77,0.62,0.92C17.19,6.55,19,9.06,19,12 c0,2.94-1.81,5.45-4.38,6.49C14.25,18.64,14,19.01,14,19.41v0c0,0.7,0.71,1.19,1.36,0.93C18.67,19.02,21,15.78,21,12 C21,8.22,18.67,4.98,15.36,3.65z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_apps.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_apps.xml
index ab58f204..d62b777 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_apps.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_apps.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M 4 4 H 8 V 8 H 4 V 4 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 4 10 H 8 V 14 H 4 V 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 4 16 H 8 V 20 H 4 V 16 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 10 4 H 14 V 8 H 10 V 4 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 10 10 H 14 V 14 H 10 V 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 10 16 H 14 V 20 H 10 V 16 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 16 4 H 20 V 8 H 16 V 4 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 16 10 H 20 V 14 H 16 V 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 16 16 H 20 V 20 H 16 V 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 4 4 H 8 V 8 H 4 V 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 4 10 H 8 V 14 H 4 V 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 4 16 H 8 V 20 H 4 V 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 10 4 H 14 V 8 H 10 V 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 10 10 H 14 V 14 H 10 V 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 10 16 H 14 V 20 H 10 V 16 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 16 4 H 20 V 8 H 16 V 4 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 16 10 H 20 V 14 H 16 V 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 16 16 H 20 V 20 H 16 V 16 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_devices_other.xml
index 7548dfa..71fb7a3 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:autoMirrored="true" android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M21.5,8h-5L15,9.5v9l1.5,1.5h5l1.5-1.5v-9L21.5,8z M21.5,18.5h-5v-9h5V18.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 2.5 5.5 L 21 5.5 L 21 4 L 2.5 4 L 1 5.5 L 1 18.5 L 2.5 20 L 7 20 L 7 18.5 L 2.5 18.5 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M13,12H9v1.78C8.39,14.33,8,15.11,8,16s0.39,1.67,1,2.22V20h4v-1.78c0.61-0.55,1-1.34,1-2.22s-0.39-1.67-1-2.22V12z M11,14.5c0.83,0,1.5,0.67,1.5,1.5s-0.67,1.5-1.5,1.5S9.5,16.83,9.5,16S10.17,14.5,11,14.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M21.5,8h-5L15,9.5v9l1.5,1.5h5l1.5-1.5v-9L21.5,8z M21.5,18.5h-5v-9h5V18.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 2.5 5.5 L 21 5.5 L 21 4 L 2.5 4 L 1 5.5 L 1 18.5 L 2.5 20 L 7 20 L 7 18.5 L 2.5 18.5 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M13,12H9v1.78C8.39,14.33,8,15.11,8,16s0.39,1.67,1,2.22V20h4v-1.78c0.61-0.55,1-1.34,1-2.22s-0.39-1.67-1-2.22V12z M11,14.5c0.83,0,1.5,0.67,1.5,1.5s-0.67,1.5-1.5,1.5S9.5,16.83,9.5,16S10.17,14.5,11,14.5z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_help.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_help.xml
index eb2e966..32c603d 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_help.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_help.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M12,20.5c-4.69,0-8.5-3.81-8.5-8.5S7.31,3.5,12,3.5 s8.5,3.81,8.5,8.5S16.69,20.5,12,20.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12.48,6c-1.71,0-3.53,0.96-3.53,3.17v0.37c0,0.11,0.06,0.17,0.17,0.17l1.29,0.07c0.11,0,0.17-0.06,0.17-0.17V9.17 c0-1.29,1.07-1.7,1.85-1.7c0.74,0,1.81,0.37,1.81,1.66c0,1.48-1.57,1.85-2.54,3.09c-0.48,0.6-0.39,1.28-0.39,2.1 c0,0.09,0.08,0.17,0.17,0.17l1.3,0c0.11,0,0.17-0.06,0.17-0.17c0-0.72-0.07-1.13,0.28-1.54c0.91-1.05,2.65-1.46,2.65-3.7 C15.89,6.99,14.27,6,12.48,6z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12.83,16h-1.66C11.08,16,11,16.08,11,16.17v1.66c0,0.09,0.08,0.17,0.17,0.17h1.66c0.09,0,0.17-0.08,0.17-0.17v-1.66 C13,16.08,12.92,16,12.83,16z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M12,20.5c-4.69,0-8.5-3.81-8.5-8.5S7.31,3.5,12,3.5 s8.5,3.81,8.5,8.5S16.69,20.5,12,20.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12.48,6c-1.71,0-3.53,0.96-3.53,3.17v0.37c0,0.11,0.06,0.17,0.17,0.17l1.29,0.07c0.11,0,0.17-0.06,0.17-0.17V9.17 c0-1.29,1.07-1.7,1.85-1.7c0.74,0,1.81,0.37,1.81,1.66c0,1.48-1.57,1.85-2.54,3.09c-0.48,0.6-0.39,1.28-0.39,2.1 c0,0.09,0.08,0.17,0.17,0.17l1.3,0c0.11,0,0.17-0.06,0.17-0.17c0-0.72-0.07-1.13,0.28-1.54c0.91-1.05,2.65-1.46,2.65-3.7 C15.89,6.99,14.27,6,12.48,6z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12.83,16h-1.66C11.08,16,11,16.08,11,16.17v1.66c0,0.09,0.08,0.17,0.17,0.17h1.66c0.09,0,0.17-0.08,0.17-0.17v-1.66 C13,16.08,12.92,16,12.83,16z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_phone_info.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_phone_info.xml
index 0484309..1307f38 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_phone_info.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_phone_info.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M 11.25 11 H 12.75 V 16 H 11.25 V 11 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 11.25 8 H 12.75 V 9.5 H 11.25 V 8 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M17.59,1H6.41L5,2.41v19.17L6.41,23h11.17L19,21.59V2.41L17.59,1z M17.5,2.5v1.75h-11V2.5H17.5z M17.5,5.75v12.5h-11V5.75 H17.5z M6.5,21.5v-1.75h11v1.75H6.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 11.25 11 H 12.75 V 16 H 11.25 V 11 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 11.25 8 H 12.75 V 9.5 H 11.25 V 8 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M17.59,1H6.41L5,2.41v19.17L6.41,23h11.17L19,21.59V2.41L17.59,1z M17.5,2.5v1.75h-11V2.5H17.5z M17.5,5.75v12.5h-11V5.75 H17.5z M6.5,21.5v-1.75h11v1.75H6.5z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_accessibility.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_accessibility.xml
index 7f80c7d..5983b89 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_accessibility.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_accessibility.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M20.5,4c-2.61,0.7-5.67,1-8.5,1S6.11,4.7,3.5,4L3,6c1.86,0.5,4,0.83,6,1v13h2v-6h2v6h2V7c2-0.17,4.14-0.5,6-1L20.5,4z M12,4c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C10,3.1,10.9,4,12,4"/>
- <path android:fillColor="@android:color/white" android:pathData="M7,24h2v-2H7V24z M11,24h2v-2h-2V24z M15,24h2v-2h-2V24z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M20.5,4c-2.61,0.7-5.67,1-8.5,1S6.11,4.7,3.5,4L3,6c1.86,0.5,4,0.83,6,1v13h2v-6h2v6h2V7c2-0.17,4.14-0.5,6-1L20.5,4z M12,4c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2s-2,0.9-2,2C10,3.1,10.9,4,12,4"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M7,24h2v-2H7V24z M11,24h2v-2h-2V24z M15,24h2v-2h-2V24z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_accounts.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_accounts.xml
index 758e63f..3a997b0 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_accounts.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_accounts.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,13c1.93,0,3.5-1.57,3.5-3.5S13.93,6,12,6S8.5,7.57,8.5,9.5S10.07,13,12,13z M12,7.5c1.1,0,2,0.9,2,2s-0.9,2-2,2 s-2-0.9-2-2S10.9,7.5,12,7.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M19.5,3h-15L3,4.5v15L4.5,21h15l1.5-1.5v-15L19.5,3z M19.5,19.5h-15v-1.65c1.76-1.53,5.37-2.35,7.5-2.35 c1.45,0,3.76,0.38,5.67,1.24c0.62,0.28,1.29,0.65,1.83,1.12V19.5z M19.5,16.02C17.26,14.64,14.04,14,12,14s-5.26,0.64-7.5,2.02 V4.5h15V16.02z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,13c1.93,0,3.5-1.57,3.5-3.5S13.93,6,12,6S8.5,7.57,8.5,9.5S10.07,13,12,13z M12,7.5c1.1,0,2,0.9,2,2s-0.9,2-2,2 s-2-0.9-2-2S10.9,7.5,12,7.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M19.5,3h-15L3,4.5v15L4.5,21h15l1.5-1.5v-15L19.5,3z M19.5,19.5h-15v-1.65c1.76-1.53,5.37-2.35,7.5-2.35 c1.45,0,3.76,0.38,5.67,1.24c0.62,0.28,1.29,0.65,1.83,1.12V19.5z M19.5,16.02C17.26,14.64,14.04,14,12,14s-5.26,0.64-7.5,2.02 V4.5h15V16.02z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_battery_white.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_battery_white.xml
index e1b7945..ca9bfc9 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_battery_white.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_battery_white.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M 16.59 4 L 15 4 L 14 2 L 10 2 L 9 4 L 7.41 4 L 6 5.41 L 6 20.59 L 7.41 22 L 16.59 22 L 18 20.59 L 18 5.41 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 16.59 4 L 15 4 L 14 2 L 10 2 L 9 4 L 7.41 4 L 6 5.41 L 6 20.59 L 7.41 22 L 16.59 22 L 18 20.59 L 18 5.41 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_display_white.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_display_white.xml
index c7d8a61..adf1c82 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_display_white.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_display_white.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,7v10c2.76,0,5-2.24,5-5S14.76,7,12,7z"/>
- <path android:fillColor="@android:color/white" android:pathData="M22.81,12.5v-1L20,8.69V4.71l0,0L19.29,4l0,0h-3.98L12.5,1.19h-1v0L8.69,4H4.71l0,0L4,4.71l0,0v3.98L1.19,11.5v1h0 L4,15.31v3.98l0,0L4.71,20l0,0h3.98l2.81,2.81v0h1L15.31,20h3.98l0,0L20,19.29l0,0v-3.98L22.81,12.5L22.81,12.5z M18.5,14.69v3.81 h-3.81L12,21.19L9.31,18.5H5.5v-3.81L2.81,12L5.5,9.31V5.5h3.81L12,2.81l2.69,2.69h3.81v3.81L21.19,12L18.5,14.69z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,7v10c2.76,0,5-2.24,5-5S14.76,7,12,7z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M22.81,12.5v-1L20,8.69V4.71l0,0L19.29,4l0,0h-3.98L12.5,1.19h-1v0L8.69,4H4.71l0,0L4,4.71l0,0v3.98L1.19,11.5v1h0 L4,15.31v3.98l0,0L4.71,20l0,0h3.98l2.81,2.81v0h1L15.31,20h3.98l0,0L20,19.29l0,0v-3.98L22.81,12.5L22.81,12.5z M18.5,14.69v3.81 h-3.81L12,21.19L9.31,18.5H5.5v-3.81L2.81,12L5.5,9.31V5.5h3.81L12,2.81l2.69,2.69h3.81v3.81L21.19,12L18.5,14.69z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_location.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_location.xml
index 7975db6..90ad165 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_location.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_location.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,2c-4.2,0-8,3.22-8,8.2c0,3.11,2.33,6.62,7,10.8h2c4.67-4.18,7-7.7,7-10.8C20,5.22,16.2,2,12,2z M12.42,19.5h-0.84 c-4.04-3.7-6.08-6.74-6.08-9.3c0-4.35,3.35-6.7,6.5-6.7s6.5,2.35,6.5,6.7C18.5,12.76,16.46,15.8,12.42,19.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12,7c-1.66,0-3,1.34-3,3c0,1.66,1.34,3,3,3s3-1.34,3-3C15,8.34,13.66,7,12,7z M12,11.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C13.5,10.83,12.83,11.5,12,11.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,2c-4.2,0-8,3.22-8,8.2c0,3.11,2.33,6.62,7,10.8h2c4.67-4.18,7-7.7,7-10.8C20,5.22,16.2,2,12,2z M12.42,19.5h-0.84 c-4.04-3.7-6.08-6.74-6.08-9.3c0-4.35,3.35-6.7,6.5-6.7s6.5,2.35,6.5,6.7C18.5,12.76,16.46,15.8,12.42,19.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,7c-1.66,0-3,1.34-3,3c0,1.66,1.34,3,3,3s3-1.34,3-3C15,8.34,13.66,7,12,7z M12,11.5c-0.83,0-1.5-0.67-1.5-1.5 c0-0.83,0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5C13.5,10.83,12.83,11.5,12,11.5z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_privacy.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_privacy.xml
index 7da20c1..f499227 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_privacy.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_privacy.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,8.5c1.48,0,2.71,1.08,2.95,2.5h1.5C16.2,8.76,14.31,7,12,7c-2.48,0-4.5,2.02-4.5,4.5c0,2.48,2.02,4.5,4.5,4.5 c0.72,0,1.39-0.19,2-0.49v-1.79c-0.53,0.48-1.23,0.78-2,0.78c-1.65,0-3-1.35-3-3S10.35,8.5,12,8.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M12,4C7.38,4,3.4,6.65,1.45,10.51v1.97C3.4,16.35,7.38,19,12,19c0.68,0,1.35-0.06,2-0.18v-1.54 c-0.65,0.13-1.32,0.22-2,0.22c-4.07,0-7.68-2.34-9.37-6c1.69-3.66,5.3-6,9.37-6c3.87,0,7.32,2.13,9.09,5.5h1.46v-0.49 C20.6,6.65,16.62,4,12,4z"/>
- <path android:fillColor="@android:color/white" android:pathData="M21,14l-1-1h-2l-1,1v2h-1v5h6v-5h-1V14z M19.5,16h-1v-1.5h1V16z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,8.5c1.48,0,2.71,1.08,2.95,2.5h1.5C16.2,8.76,14.31,7,12,7c-2.48,0-4.5,2.02-4.5,4.5c0,2.48,2.02,4.5,4.5,4.5 c0.72,0,1.39-0.19,2-0.49v-1.79c-0.53,0.48-1.23,0.78-2,0.78c-1.65,0-3-1.35-3-3S10.35,8.5,12,8.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,4C7.38,4,3.4,6.65,1.45,10.51v1.97C3.4,16.35,7.38,19,12,19c0.68,0,1.35-0.06,2-0.18v-1.54 c-0.65,0.13-1.32,0.22-2,0.22c-4.07,0-7.68-2.34-9.37-6c1.69-3.66,5.3-6,9.37-6c3.87,0,7.32,2.13,9.09,5.5h1.46v-0.49 C20.6,6.65,16.62,4,12,4z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M21,14l-1-1h-2l-1,1v2h-1v5h6v-5h-1V14z M19.5,16h-1v-1.5h1V16z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_security_white.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_security_white.xml
index fbf6ae1..49d31f7 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_security_white.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_security_white.xml
@@ -14,6 +14,6 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M21,2h-5l-1.5,1.5l0,4.5h-9L4,9.5v11L5.5,22h13l1.5-1.5v-11L18.5,8H16V3.5h5v2.62h1.5V3.5L21,2z M18.5,20.5h-13v-11h13 V20.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 12 13 C 13.1045694997 13 14 13.8954305003 14 15 C 14 16.1045694997 13.1045694997 17 12 17 C 10.8954305003 17 10 16.1045694997 10 15 C 10 13.8954305003 10.8954305003 13 12 13 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M21,2h-5l-1.5,1.5l0,4.5h-9L4,9.5v11L5.5,22h13l1.5-1.5v-11L18.5,8H16V3.5h5v2.62h1.5V3.5L21,2z M18.5,20.5h-13v-11h13 V20.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 12 13 C 13.1045694997 13 14 13.8954305003 14 15 C 14 16.1045694997 13.1045694997 17 12 17 C 10.8954305003 17 10 16.1045694997 10 15 C 10 13.8954305003 10.8954305003 13 12 13 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
index 0594b9a..b668eb2 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_system_dashboard_white.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M12,20.5c-4.69,0-8.5-3.81-8.5-8.5S7.31,3.5,12,3.5 s8.5,3.81,8.5,8.5S16.69,20.5,12,20.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 11.25 10 H 12.75 V 17 H 11.25 V 10 Z"/>
- <path android:fillColor="@android:color/white" android:pathData="M 11.25 7 H 12.75 V 8.5 H 11.25 V 7 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M12,20.5c-4.69,0-8.5-3.81-8.5-8.5S7.31,3.5,12,3.5 s8.5,3.81,8.5,8.5S16.69,20.5,12,20.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 11.25 10 H 12.75 V 17 H 11.25 V 10 Z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M 11.25 7 H 12.75 V 8.5 H 11.25 V 7 Z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_wireless.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_wireless.xml
index 802a041..9223902 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_wireless.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_settings_wireless.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:tint="?android:attr/colorControlNormal" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M12,4.5c-4.29,0-8.17,1.72-11.01,4.49l1.42,1.42C4.89,8,8.27,6.5,12,6.5c3.73,0,7.11,1.5,9.59,3.91l1.42-1.42 C20.17,6.22,16.29,4.5,12,4.5z"/>
- <path android:fillColor="@android:color/white" android:pathData="M4.93,12.93l1.42,1.42C7.79,12.9,9.79,12,12,12s4.21,0.9,5.65,2.35l1.42-1.42C17.26,11.12,14.76,10,12,10 S6.74,11.12,4.93,12.93z"/>
- <path android:fillColor="@android:color/white" android:pathData="M9.06,17.06L12,20l2.94-2.94c-0.73-0.8-1.77-1.31-2.94-1.31S9.79,16.26,9.06,17.06z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M12,4.5c-4.29,0-8.17,1.72-11.01,4.49l1.42,1.42C4.89,8,8.27,6.5,12,6.5c3.73,0,7.11,1.5,9.59,3.91l1.42-1.42 C20.17,6.22,16.29,4.5,12,4.5z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M4.93,12.93l1.42,1.42C7.79,12.9,9.79,12,12,12s4.21,0.9,5.65,2.35l1.42-1.42C17.26,11.12,14.76,10,12,10 S6.74,11.12,4.93,12.93z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M9.06,17.06L12,20l2.94-2.94c-0.73-0.8-1.77-1.31-2.94-1.31S9.79,16.26,9.06,17.06z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_storage_white.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_storage_white.xml
index 45288f9..22f6092 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_storage_white.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_storage_white.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M19.5,4h-15L3,5.5v1L4.5,8h15L21,6.5v-1L19.5,4z M6.5,6.75H5v-1.5h1.5V6.75z"/>
- <path android:fillColor="@android:color/white" android:pathData="M4.5,10L3,11.5v1L4.5,14h15l1.5-1.5v-1L19.5,10H4.5z M6.5,12.75H5v-1.5h1.5V12.75z"/>
- <path android:fillColor="@android:color/white" android:pathData="M4.5,16L3,17.5v1L4.5,20h15l1.5-1.5v-1L19.5,16H4.5z M6.5,18.75H5v-1.5h1.5V18.75z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M19.5,4h-15L3,5.5v1L4.5,8h15L21,6.5v-1L19.5,4z M6.5,6.75H5v-1.5h1.5V6.75z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M4.5,10L3,11.5v1L4.5,14h15l1.5-1.5v-1L19.5,10H4.5z M6.5,12.75H5v-1.5h1.5V12.75z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M4.5,16L3,17.5v1L4.5,20h15l1.5-1.5v-1L19.5,16H4.5z M6.5,18.75H5v-1.5h1.5V18.75z"/>
</vector>
\ No newline at end of file
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_volume_up_24dp.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
index 781ed94..964f668 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
+++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_volume_up_24dp.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="@android:color/white" android:pathData="M7,9H4.5L3,10.5v3L4.5,15H7l4,4h1V5h-1L7,9z M10.5,16.38L7.62,13.5H4.5v-3h3.12l2.88-2.88V16.38z"/>
- <path android:fillColor="@android:color/white" android:pathData="M14,3.23v1.55c3.17,0.88,5.5,3.78,5.5,7.22s-2.33,6.34-5.5,7.22v1.55c4.01-0.91,7-4.49,7-8.77S18.01,4.14,14,3.23z"/>
- <path android:fillColor="@android:color/white" android:pathData="M16.5,12c0-1.76-1.02-3.27-2.5-4.01v8.02C15.48,15.27,16.5,13.76,16.5,12z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M7,9H4.5L3,10.5v3L4.5,15H7l4,4h1V5h-1L7,9z M10.5,16.38L7.62,13.5H4.5v-3h3.12l2.88-2.88V16.38z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M14,3.23v1.55c3.17,0.88,5.5,3.78,5.5,7.22s-2.33,6.34-5.5,7.22v1.55c4.01-0.91,7-4.49,7-8.77S18.01,4.14,14,3.23z"/>
+ <path android:fillColor="?android:attr/colorPrimary" android:pathData="M16.5,12c0-1.76-1.02-3.27-2.5-4.01v8.02C15.48,15.27,16.5,13.76,16.5,12z"/>
</vector>
\ No newline at end of file
diff --git a/packages/services/CameraExtensionsProxy/OWNERS b/packages/services/CameraExtensionsProxy/OWNERS
new file mode 100644
index 0000000..f48a95c
--- /dev/null
+++ b/packages/services/CameraExtensionsProxy/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/av:/camera/OWNERS
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
index ac40222..f8b9309 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
@@ -19,8 +19,8 @@
import android.util.Log;
import com.android.net.IProxyPortListener;
+
import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
import java.io.IOException;
import java.io.InputStream;
@@ -34,7 +34,6 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -361,7 +360,7 @@
try {
mCallback.setProxyPort(port);
} catch (RemoteException e) {
- Log.w(TAG, "Proxy failed to report port to PacManager", e);
+ Log.w(TAG, "Proxy failed to report port to PacProxyInstaller", e);
}
}
mPort = port;
@@ -372,7 +371,7 @@
try {
callback.setProxyPort(mPort);
} catch (RemoteException e) {
- Log.w(TAG, "Proxy failed to report port to PacManager", e);
+ Log.w(TAG, "Proxy failed to report port to PacProxyInstaller", e);
}
}
mCallback = callback;
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
index 970fdc7..bdf478d 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
@@ -30,7 +30,7 @@
private static ProxyServer server = null;
- /** Keep these values up-to-date with PacManager.java */
+ /** Keep these values up-to-date with PacProxyInstaller.java */
public static final String KEY_PROXY = "keyProxy";
public static final String HOST = "localhost";
public static final String EXCL_LIST = "";
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 449063d..d4bd5ad 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -222,6 +222,7 @@
private final SparseIntArray mLoadedUserIds = new SparseIntArray();
+ private final Object mWidgetPackagesLock = new Object();
private final SparseArray<ArraySet<String>> mWidgetPackages = new SparseArray<>();
private BackupRestoreController mBackupRestoreController;
@@ -2941,11 +2942,13 @@
if (widget.provider == null) return;
int userId = widget.provider.getUserId();
- ArraySet<String> packages = mWidgetPackages.get(userId);
- if (packages == null) {
- mWidgetPackages.put(userId, packages = new ArraySet<String>());
+ synchronized (mWidgetPackagesLock) {
+ ArraySet<String> packages = mWidgetPackages.get(userId);
+ if (packages == null) {
+ mWidgetPackages.put(userId, packages = new ArraySet<String>());
+ }
+ packages.add(widget.provider.info.provider.getPackageName());
}
- packages.add(widget.provider.info.provider.getPackageName());
// If we are adding a widget it might be for a provider that
// is currently masked, if so mask the widget.
@@ -2972,22 +2975,24 @@
final int userId = widget.provider.getUserId();
final String packageName = widget.provider.info.provider.getPackageName();
- ArraySet<String> packages = mWidgetPackages.get(userId);
- if (packages == null) {
- return;
- }
- // Check if there is any other widget with the same package name.
- // Remove packageName if none.
- final int N = mWidgets.size();
- for (int i = 0; i < N; i++) {
- Widget w = mWidgets.get(i);
- if (w.provider == null) continue;
- if (w.provider.getUserId() == userId
- && packageName.equals(w.provider.info.provider.getPackageName())) {
+ synchronized (mWidgetPackagesLock) {
+ ArraySet<String> packages = mWidgetPackages.get(userId);
+ if (packages == null) {
return;
}
+ // Check if there is any other widget with the same package name.
+ // Remove packageName if none.
+ final int N = mWidgets.size();
+ for (int i = 0; i < N; i++) {
+ Widget w = mWidgets.get(i);
+ if (w.provider == null) continue;
+ if (w.provider.getUserId() == userId
+ && packageName.equals(w.provider.info.provider.getPackageName())) {
+ return;
+ }
+ }
+ packages.remove(packageName);
}
- packages.remove(packageName);
}
/**
@@ -3000,7 +3005,9 @@
}
private void onWidgetsClearedLocked() {
- mWidgetPackages.clear();
+ synchronized (mWidgetPackagesLock) {
+ mWidgetPackages.clear();
+ }
}
@Override
@@ -3008,7 +3015,7 @@
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Only the system process can call this");
}
- synchronized (mLock) {
+ synchronized (mWidgetPackagesLock) {
final ArraySet<String> packages = mWidgetPackages.get(userId);
if (packages != null) {
return packages.contains(packageName);
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 53bfcec..dad8bd8 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1139,4 +1139,15 @@
@Checksum.Type int optional, @Checksum.Type int required,
@Nullable List trustedInstallers, @NonNull IntentSender statusReceiver, int userId,
@NonNull Executor executor, @NonNull Handler handler);
+
+ /**
+ * Returns true if the given {@code packageName} and {@code userId} is frozen.
+ *
+ * @param packageName a specific package
+ * @param callingUid The uid of the caller
+ * @param userId The user for whom the package is installed
+ * @return {@code true} If the package is current frozen (due to install/update etc.)
+ */
+ public abstract boolean isPackageFrozen(
+ @NonNull String packageName, int callingUid, int userId);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index deafd93..53a8597 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -28,7 +28,6 @@
import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS;
import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
-import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_NONE;
@@ -195,7 +194,6 @@
import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
-import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.KeepaliveTracker;
import com.android.server.connectivity.LingerMonitor;
import com.android.server.connectivity.MockableSystemProperties;
@@ -919,14 +917,6 @@
return new MultinetworkPolicyTracker(c, h, r);
}
- /**
- * @see IpConnectivityMetrics.Logger
- */
- public IpConnectivityMetrics.Logger getMetricsLogger() {
- return Objects.requireNonNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
- "no IpConnectivityMetrics service");
- }
-
public IBatteryStats getBatteryStatsService() {
return BatteryStatsService.getService();
}
@@ -1444,31 +1434,20 @@
}
private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) {
- final int user = UserHandle.getUserId(uid);
- int vpnNetId = NETID_UNSET;
- synchronized (mVpns) {
- final Vpn vpn = mVpns.get(user);
- // TODO : now that capabilities contain the UID, the appliesToUid test should
- // be removed as the satisfying test below should be enough.
- if (vpn != null && vpn.appliesToUid(uid)) vpnNetId = vpn.getNetId();
- }
- NetworkAgentInfo nai;
- if (vpnNetId != NETID_UNSET) {
- nai = getNetworkAgentInfoForNetId(vpnNetId);
- if (nai != null) {
- final NetworkCapabilities requiredCaps =
- createDefaultNetworkCapabilitiesForUid(uid);
- if (requiredCaps.satisfiedByNetworkCapabilities(nai.networkCapabilities)) {
- return nai.network;
- }
+ final NetworkAgentInfo vpnNai = getVpnForUid(uid);
+ if (vpnNai != null) {
+ final NetworkCapabilities requiredCaps = createDefaultNetworkCapabilitiesForUid(uid);
+ if (requiredCaps.satisfiedByNetworkCapabilities(vpnNai.networkCapabilities)) {
+ return vpnNai.network;
}
}
- nai = getDefaultNetwork();
- if (nai != null && isNetworkWithCapabilitiesBlocked(
- nai.networkCapabilities, uid, ignoreBlocked)) {
- nai = null;
+
+ NetworkAgentInfo nai = getDefaultNetwork();
+ if (nai == null || isNetworkWithCapabilitiesBlocked(nai.networkCapabilities, uid,
+ ignoreBlocked)) {
+ return null;
}
- return nai != null ? nai.network : null;
+ return nai.network;
}
// Public because it's used by mLockdownTracker.
@@ -1819,12 +1798,28 @@
private INetworkManagementEventObserver mDataActivityObserver = new BaseNetworkObserver() {
@Override
- public void interfaceClassDataActivityChanged(int networkType, boolean active, long tsNanos,
- int uid) {
- sendDataActivityBroadcast(networkType, active, tsNanos);
+ public void interfaceClassDataActivityChanged(int transportType, boolean active,
+ long tsNanos, int uid) {
+ sendDataActivityBroadcast(transportTypeToLegacyType(transportType), active, tsNanos);
}
};
+ // This is deprecated and only to support legacy use cases.
+ private int transportTypeToLegacyType(int type) {
+ switch (type) {
+ case NetworkCapabilities.TRANSPORT_CELLULAR:
+ return ConnectivityManager.TYPE_MOBILE;
+ case NetworkCapabilities.TRANSPORT_WIFI:
+ return ConnectivityManager.TYPE_WIFI;
+ case NetworkCapabilities.TRANSPORT_BLUETOOTH:
+ return ConnectivityManager.TYPE_BLUETOOTH;
+ case NetworkCapabilities.TRANSPORT_ETHERNET:
+ return ConnectivityManager.TYPE_ETHERNET;
+ default:
+ loge("Unexpected transport in transportTypeToLegacyType: " + type);
+ }
+ return ConnectivityManager.TYPE_NONE;
+ }
/**
* Ensures that the system cannot call a particular method.
*/
@@ -2408,13 +2403,13 @@
timeout = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
10);
- type = ConnectivityManager.TYPE_MOBILE;
+ type = NetworkCapabilities.TRANSPORT_CELLULAR;
} else if (networkAgent.networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_WIFI)) {
timeout = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
15);
- type = ConnectivityManager.TYPE_WIFI;
+ type = NetworkCapabilities.TRANSPORT_WIFI;
} else {
return; // do not track any other networks
}
@@ -4830,15 +4825,15 @@
if (mLockdownEnabled) {
return new VpnInfo[0];
}
- List<VpnInfo> infoList = new ArrayList<>();
- for (NetworkAgentInfo nai : mNetworkAgentInfos) {
- VpnInfo info = createVpnInfo(nai);
- if (info != null) {
- infoList.add(info);
- }
- }
- return infoList.toArray(new VpnInfo[infoList.size()]);
}
+ List<VpnInfo> infoList = new ArrayList<>();
+ for (NetworkAgentInfo nai : mNetworkAgentInfos) {
+ VpnInfo info = createVpnInfo(nai);
+ if (info != null) {
+ infoList.add(info);
+ }
+ }
+ return infoList.toArray(new VpnInfo[infoList.size()]);
}
/**
@@ -5654,31 +5649,40 @@
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
- Messenger messenger, int timeoutMs, IBinder binder, int legacyType,
- @NonNull String callingPackageName, @Nullable String callingAttributionTag) {
+ int reqTypeInt, Messenger messenger, int timeoutMs, IBinder binder,
+ int legacyType, @NonNull String callingPackageName,
+ @Nullable String callingAttributionTag) {
if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) {
if (checkUnsupportedStartingFrom(Build.VERSION_CODES.M, callingPackageName)) {
throw new SecurityException("Insufficient permissions to specify legacy type");
}
}
final int callingUid = mDeps.getCallingUid();
- final NetworkRequest.Type type = (networkCapabilities == null)
- ? NetworkRequest.Type.TRACK_DEFAULT
- : NetworkRequest.Type.REQUEST;
- // If the requested networkCapabilities is null, take them instead from
- // the default network request. This allows callers to keep track of
- // the system default network.
- if (type == NetworkRequest.Type.TRACK_DEFAULT) {
- networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid);
- enforceAccessPermission();
- } else {
- networkCapabilities = new NetworkCapabilities(networkCapabilities);
- enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
- callingAttributionTag);
- // TODO: this is incorrect. We mark the request as metered or not depending on the state
- // of the app when the request is filed, but we never change the request if the app
- // changes network state. http://b/29964605
- enforceMeteredApnPolicy(networkCapabilities);
+ final NetworkRequest.Type reqType;
+ try {
+ reqType = NetworkRequest.Type.values()[reqTypeInt];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException("Unsupported request type " + reqTypeInt);
+ }
+ switch (reqType) {
+ case TRACK_DEFAULT:
+ // If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities}
+ // is unused and will be replaced by the one from the default network request.
+ // This allows callers to keep track of the system default network.
+ networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid);
+ enforceAccessPermission();
+ break;
+ case REQUEST:
+ networkCapabilities = new NetworkCapabilities(networkCapabilities);
+ enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
+ callingAttributionTag);
+ // TODO: this is incorrect. We mark the request as metered or not depending on
+ // the state of the app when the request is filed, but we never change the
+ // request if the app changes network state. http://b/29964605
+ enforceMeteredApnPolicy(networkCapabilities);
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported request type " + reqType);
}
ensureRequestableCapabilities(networkCapabilities);
ensureSufficientPermissionsForRequest(networkCapabilities,
@@ -5697,7 +5701,7 @@
ensureValid(networkCapabilities);
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
- nextNetworkRequestId(), type);
+ nextNetworkRequestId(), reqType);
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder);
if (DBG) log("requestNetwork for " + nri);
@@ -6593,7 +6597,7 @@
}
// Don't modify caller's NetworkCapabilities.
- NetworkCapabilities newNc = new NetworkCapabilities(nc);
+ final NetworkCapabilities newNc = new NetworkCapabilities(nc);
if (nai.lastValidated) {
newNc.addCapability(NET_CAPABILITY_VALIDATED);
} else {
@@ -6681,26 +6685,21 @@
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
- // TODO : static analysis indicates that prevNc can't be null here (getAndSetNetworkCaps
- // never returns null), so mark the relevant members and functions in nai as @NonNull and
- // remove this test
- if (prevNc != null) {
- final boolean oldMetered = prevNc.isMetered();
- final boolean newMetered = newNc.isMetered();
- final boolean meteredChanged = oldMetered != newMetered;
+ final boolean oldMetered = prevNc.isMetered();
+ final boolean newMetered = newNc.isMetered();
+ final boolean meteredChanged = oldMetered != newMetered;
- if (meteredChanged) {
- maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground,
- mRestrictBackground, mVpnBlockedUidRanges, mVpnBlockedUidRanges);
- }
+ if (meteredChanged) {
+ maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground,
+ mRestrictBackground, mVpnBlockedUidRanges, mVpnBlockedUidRanges);
+ }
- final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) !=
- newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+ final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING)
+ != newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
- // Report changes that are interesting for network statistics tracking.
- if (meteredChanged || roamingChanged) {
- notifyIfacesChangedForNetworkStats();
- }
+ // Report changes that are interesting for network statistics tracking.
+ if (meteredChanged || roamingChanged) {
+ notifyIfacesChangedForNetworkStats();
}
// This network might have been underlying another network. Propagate its capabilities.
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index 9ba71dc..e99bb24 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -283,11 +283,16 @@
mIndividualEnabled.put(userId, userIndividualEnabled);
if (!enable) {
- // Remove any notifications prompting the user to disable sensory privacy
- NotificationManager notificationManager =
- mContext.getSystemService(NotificationManager.class);
+ long token = Binder.clearCallingIdentity();
+ try {
+ // Remove any notifications prompting the user to disable sensory privacy
+ NotificationManager notificationManager =
+ mContext.getSystemService(NotificationManager.class);
- notificationManager.cancel(sensor);
+ notificationManager.cancel(sensor);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
persistSensorPrivacyState();
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index b76f3278..dde182b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -564,8 +564,7 @@
mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
- mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig(
- PhysicalChannelConfig.CONNECTION_UNKNOWN,0));
+ mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
}
}
@@ -656,8 +655,7 @@
mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
- mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig(
- PhysicalChannelConfig.CONNECTION_UNKNOWN,0));
+ mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7af328a..88bb1a0 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -70,6 +70,7 @@
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -171,6 +172,7 @@
public static final int FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES = 20;
public static final int FGS_FEATURE_ALLOWED_BY_ACTIVITY_STARTER = 21;
public static final int FGS_FEATURE_ALLOWED_BY_COMPANION_APP = 22;
+ public static final int FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER = 23;
@IntDef(flag = true, prefix = { "FGS_FEATURE_" }, value = {
FGS_FEATURE_DENIED,
@@ -194,7 +196,8 @@
FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD,
FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES,
FGS_FEATURE_ALLOWED_BY_ACTIVITY_STARTER,
- FGS_FEATURE_ALLOWED_BY_COMPANION_APP
+ FGS_FEATURE_ALLOWED_BY_COMPANION_APP,
+ FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER
})
@Retention(RetentionPolicy.SOURCE)
public @interface FgsFeatureRetCode {}
@@ -246,6 +249,11 @@
*/
final ArrayList<ServiceRecord> mPendingFgsNotifications = new ArrayList<>();
+ /**
+ * Map of services that are asked to be brought up (start/binding) but not ready to.
+ */
+ private ArrayMap<ServiceRecord, ArrayList<Runnable>> mPendingBringups = new ArrayMap<>();
+
/** Temporary list for holding the results of calls to {@link #collectPackageServicesLocked} */
private ArrayList<ServiceRecord> mTmpCollectionResults = null;
@@ -767,8 +775,13 @@
fgRequired = false;
}
- NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent(
- service, callingUid, r.packageName, r.userId);
+ // The package could be frozen (meaning it's doing surgery), defer the actual
+ // start until the package is unfrozen.
+ if (deferServiceBringupIfFrozenLocked(r, service, callingPackage, callingFeatureId,
+ callingUid, callingPid, fgRequired, callerFg, userId, allowBackgroundActivityStarts,
+ backgroundActivityStartsToken, false, null)) {
+ return null;
+ }
// If permissions need a review before any of the app components can run,
// we do not start the service and launch a review activity if the calling app
@@ -777,10 +790,20 @@
// XXX This is not dealing with fgRequired!
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage, callingFeatureId,
- callingUid, service, callerFg, userId)) {
+ callingUid, service, callerFg, userId, false, null)) {
return null;
}
+ return startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg,
+ allowBackgroundActivityStarts, backgroundActivityStartsToken);
+ }
+
+ private ComponentName startServiceInnerLocked(ServiceRecord r, Intent service,
+ int callingUid, int callingPid, boolean fgRequired, boolean callerFg,
+ boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken)
+ throws TransactionTooLargeException {
+ NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent(
+ service, callingUid, r.packageName, r.userId);
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
}
@@ -876,30 +899,72 @@
private boolean requestStartTargetPermissionsReviewIfNeededLocked(ServiceRecord r,
String callingPackage, @Nullable String callingFeatureId, int callingUid,
- Intent service, boolean callerFg, final int userId) {
+ Intent service, boolean callerFg, final int userId,
+ final boolean isBinding, final IServiceConnection connection) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
r.packageName, r.userId)) {
- // Show a permission review UI only for starting from a foreground app
+ // Show a permission review UI only for starting/binding from a foreground app
if (!callerFg) {
- Slog.w(TAG, "u" + r.userId + " Starting a service in package"
+ Slog.w(TAG, "u" + r.userId
+ + (isBinding ? " Binding" : " Starting") + " a service in package"
+ r.packageName + " requires a permissions review");
return false;
}
- IIntentSender target = mAm.mPendingIntentController.getIntentSender(
- ActivityManager.INTENT_SENDER_SERVICE, callingPackage, callingFeatureId,
- callingUid, userId, null, null, 0, new Intent[]{service},
- new String[]{service.resolveType(mAm.mContext.getContentResolver())},
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
- | PendingIntent.FLAG_IMMUTABLE, null);
-
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, r.packageName);
- intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
+
+ if (isBinding) {
+ RemoteCallback callback = new RemoteCallback(
+ new RemoteCallback.OnResultListener() {
+ @Override
+ public void onResult(Bundle result) {
+ synchronized (mAm) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (!mPendingServices.contains(r)) {
+ return;
+ }
+ // If there is still a pending record, then the service
+ // binding request is still valid, so hook them up. We
+ // proceed only if the caller cleared the review requirement
+ // otherwise we unbind because the user didn't approve.
+ if (!mAm.getPackageManagerInternalLocked()
+ .isPermissionsReviewRequired(r.packageName,
+ r.userId)) {
+ try {
+ bringUpServiceLocked(r,
+ service.getFlags(),
+ callerFg,
+ false /* whileRestarting */,
+ false /* permissionsReviewRequired */,
+ false /* packageFrozen */);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
+ } else {
+ unbindServiceLocked(connection);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+ });
+ intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
+ } else { // Starting a service
+ IIntentSender target = mAm.mPendingIntentController.getIntentSender(
+ ActivityManager.INTENT_SENDER_SERVICE, callingPackage, callingFeatureId,
+ callingUid, userId, null, null, 0, new Intent[]{service},
+ new String[]{service.resolveType(mAm.mContext.getContentResolver())},
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT
+ | PendingIntent.FLAG_IMMUTABLE, null);
+ intent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
+ }
if (DEBUG_PERMISSIONS_REVIEW) {
Slog.i(TAG, "u" + r.userId + " Launching permission review for package "
@@ -919,6 +984,84 @@
return true;
}
+ /**
+ * Defer the service starting/binding until the package is unfrozen, if it's currently frozen.
+ *
+ * @return {@code true} if the binding is deferred because it's frozen.
+ */
+ @GuardedBy("mAm")
+ private boolean deferServiceBringupIfFrozenLocked(ServiceRecord s, Intent serviceIntent,
+ String callingPackage, @Nullable String callingFeatureId,
+ int callingUid, int callingPid, boolean fgRequired, boolean callerFg, int userId,
+ boolean allowBackgroundActivityStarts, @Nullable IBinder backgroundActivityStartsToken,
+ boolean isBinding, IServiceConnection connection) {
+ final PackageManagerInternal pm = mAm.getPackageManagerInternalLocked();
+ final boolean frozen = pm.isPackageFrozen(s.packageName, callingUid, s.userId);
+ if (!frozen) {
+ // Not frozen, it's okay to go
+ return false;
+ }
+ ArrayList<Runnable> curPendingBringups = mPendingBringups.get(s);
+ if (curPendingBringups == null) {
+ curPendingBringups = new ArrayList<>();
+ mPendingBringups.put(s, curPendingBringups);
+ }
+ curPendingBringups.add(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mAm) {
+ if (!mPendingBringups.containsKey(s)) {
+ return;
+ }
+ // binding request is still valid, so hook them up.
+ // Before doing so, check if it requires a permission review.
+ if (!requestStartTargetPermissionsReviewIfNeededLocked(s,
+ callingPackage, callingFeatureId, callingUid,
+ serviceIntent, callerFg, userId, isBinding, connection)) {
+ // Let's wait for the user approval.
+ return;
+ }
+ if (isBinding) {
+ try {
+ bringUpServiceLocked(s, serviceIntent.getFlags(), callerFg,
+ false /* whileRestarting */,
+ false /* permissionsReviewRequired */,
+ false /* packageFrozen */);
+ } catch (TransactionTooLargeException e) {
+ /* ignore - local call */
+ }
+ } else { // Starting a service
+ try {
+ startServiceInnerLocked(s, serviceIntent, callingUid, callingPid,
+ fgRequired, callerFg, allowBackgroundActivityStarts,
+ backgroundActivityStartsToken);
+ } catch (TransactionTooLargeException e) {
+ /* ignore - local call */
+ }
+ }
+ }
+ }
+ });
+ return true;
+ }
+
+ @GuardedBy("mAm")
+ void schedulePendingServiceStartLocked(String packageName, int userId) {
+ for (int i = mPendingBringups.size() - 1; i >= 0; i--) {
+ final ServiceRecord r = mPendingBringups.keyAt(i);
+ if (r.userId != userId || !TextUtils.equals(r.packageName, packageName)) {
+ continue;
+ }
+ final ArrayList<Runnable> curPendingBringups = mPendingBringups.valueAt(i);
+ if (curPendingBringups != null) {
+ for (int j = curPendingBringups.size() - 1; j >= 0; j--) {
+ curPendingBringups.get(j).run();
+ }
+ }
+ mPendingBringups.removeAt(i);
+ }
+ }
+
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
@@ -930,7 +1073,7 @@
r.name.getPackageName(), r.name.getClassName(),
FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START);
mAm.mBatteryStatsService.noteServiceStartRunning(r.stats);
- String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
+ String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
@@ -1351,7 +1494,7 @@
.setContentText(msg)
.setContentIntent(
PendingIntent.getActivityAsUser(context, 0, intent,
- PendingIntent.FLAG_UPDATE_CURRENT,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED,
null, new UserHandle(smap.mUserId)));
nm.notifyAsUser(null, SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
n.build(), new UserHandle(smap.mUserId));
@@ -2224,81 +2367,19 @@
return -1;
}
ServiceRecord s = res.record;
- boolean permissionsReviewRequired = false;
+
+ // The package could be frozen (meaning it's doing surgery), defer the actual
+ // binding until the package is unfrozen.
+ boolean packageFrozen = deferServiceBringupIfFrozenLocked(s, service, callingPackage, null,
+ callingUid, callingPid, false, callerFg, userId, false, null, true, connection);
// If permissions need a review before any of the app components can run,
// we schedule binding to the service but do not start its process, then
// we launch a review activity to which is passed a callback to invoke
// when done to start the bound service's process to completing the binding.
- if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
- s.packageName, s.userId)) {
-
- permissionsReviewRequired = true;
-
- // Show a permission review UI only for binding from a foreground app
- if (!callerFg) {
- Slog.w(TAG, "u" + s.userId + " Binding to a service in package"
- + s.packageName + " requires a permissions review");
- return 0;
- }
-
- final ServiceRecord serviceRecord = s;
- final Intent serviceIntent = service;
-
- RemoteCallback callback = new RemoteCallback(
- new RemoteCallback.OnResultListener() {
- @Override
- public void onResult(Bundle result) {
- synchronized(mAm) {
- final long identity = Binder.clearCallingIdentity();
- try {
- if (!mPendingServices.contains(serviceRecord)) {
- return;
- }
- // If there is still a pending record, then the service
- // binding request is still valid, so hook them up. We
- // proceed only if the caller cleared the review requirement
- // otherwise we unbind because the user didn't approve.
- if (!mAm.getPackageManagerInternalLocked()
- .isPermissionsReviewRequired(
- serviceRecord.packageName,
- serviceRecord.userId)) {
- try {
- bringUpServiceLocked(serviceRecord,
- serviceIntent.getFlags(),
- callerFg, false, false);
- } catch (RemoteException e) {
- /* ignore - local call */
- }
- } else {
- unbindServiceLocked(connection);
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
- });
-
- final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
- intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
-
- if (DEBUG_PERMISSIONS_REVIEW) {
- Slog.i(TAG, "u" + s.userId + " Launching permission review for package "
- + s.packageName);
- }
-
- mAm.mHandler.post(new Runnable() {
- @Override
- public void run() {
- mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
- }
- });
- }
+ boolean permissionsReviewRequired = !packageFrozen
+ && !requestStartTargetPermissionsReviewIfNeededLocked(s, callingPackage, null,
+ callingUid, service, callerFg, userId, true, connection);
final long origId = Binder.clearCallingIdentity();
@@ -2372,7 +2453,7 @@
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
- permissionsReviewRequired) != null) {
+ permissionsReviewRequired, packageFrozen) != null) {
return 0;
}
}
@@ -2817,6 +2898,14 @@
mPendingServices.remove(i);
}
}
+ for (int i = mPendingBringups.size() - 1; i >= 0; i--) {
+ final ServiceRecord pr = mPendingBringups.keyAt(i);
+ if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
+ && pr.instanceName.equals(name)) {
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Remove pending bringup: " + pr);
+ mPendingBringups.removeAt(i);
+ }
+ }
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Retrieve created new service: " + r);
}
} catch (RemoteException ex) {
@@ -3110,7 +3199,8 @@
return;
}
try {
- bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false);
+ bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false,
+ false);
} catch (TransactionTooLargeException e) {
// Ignore, it's been logged and nothing upstack cares.
}
@@ -3155,7 +3245,7 @@
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
- boolean whileRestarting, boolean permissionsReviewRequired)
+ boolean whileRestarting, boolean permissionsReviewRequired, boolean packageFrozen)
throws TransactionTooLargeException {
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
@@ -3249,7 +3339,7 @@
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
- if (app == null && !permissionsReviewRequired) {
+ if (app == null && !permissionsReviewRequired && !packageFrozen) {
// TODO (chriswailes): Change the Zygote policy flags based on if the launch-for-service
// was initiated from a notification tap or not.
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
@@ -3651,6 +3741,9 @@
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r);
}
}
+ if (mPendingBringups.remove(r) != null) {
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending bringup: " + r);
+ }
cancelForegroundNotificationLocked(r);
if (r.isForeground) {
@@ -3820,6 +3913,7 @@
// remove the pending service
if (s.getConnections().isEmpty()) {
mPendingServices.remove(s);
+ mPendingBringups.remove(s);
}
if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
@@ -4144,6 +4238,12 @@
requestUpdateActiveForegroundAppsLocked(smap, 0);
}
}
+ for (int i = mPendingBringups.size() - 1; i >= 0; i--) {
+ ServiceRecord r = mPendingBringups.keyAt(i);
+ if (TextUtils.equals(r.packageName, packageName) && r.userId == userId) {
+ mPendingBringups.removeAt(i);
+ }
+ }
}
void cleanUpServices(int userId, ComponentName component, Intent baseIntent) {
@@ -4357,6 +4457,13 @@
mPendingServices.remove(i);
}
}
+ for (int i = mPendingBringups.size() - 1; i >= 0; i--) {
+ ServiceRecord r = mPendingBringups.keyAt(i);
+ if (r.processName.equals(app.processName)
+ && r.serviceInfo.applicationInfo.uid == app.info.uid) {
+ mPendingBringups.removeAt(i);
+ }
+ }
}
// Make sure we have no more records on the stopping list.
@@ -5373,6 +5480,14 @@
}
}
+ if (ret == FGS_FEATURE_DENIED) {
+ // Is the calling UID a profile owner app?
+ final boolean isProfileOwner = mAm.mInternal.isProfileOwner(callingUid);
+ if (isProfileOwner) {
+ ret = FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER;
+ }
+ }
+
// NOTE this should always be the last check.
if (ret == FGS_FEATURE_DENIED) {
if (isPackageExemptedFromFgsRestriction(r.appInfo.packageName, r.appInfo.uid)
@@ -5474,6 +5589,8 @@
return "ALLOWED_BY_ACTIVITY_STARTER";
case FGS_FEATURE_ALLOWED_BY_COMPANION_APP:
return "ALLOWED_BY_COMPANION_APP";
+ case FGS_FEATURE_ALLOWED_BY_PROFILE_OWNER:
+ return "ALLOWED_BY_PROFILE_OWNER";
default:
return "";
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9e62e63..b587f1b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -572,9 +572,16 @@
private int mDeviceOwnerUid = Process.INVALID_UID;
- // A map userId and all its companion app uids
+ /**
+ * Map userId to its companion app uids.
+ */
private final Map<Integer, Set<Integer>> mCompanionAppUidsMap = new ArrayMap<>();
+ /**
+ * The profile owner UIDs.
+ */
+ private ArraySet<Integer> mProfileOwnerUids = null;
+
final UserController mUserController;
@VisibleForTesting
public final PendingIntentController mPendingIntentController;
@@ -13584,6 +13591,7 @@
cleanupDisabledPackageComponentsLocked(ssp, userId,
intent.getStringArrayExtra(
Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
+ mServices.schedulePendingServiceStartLocked(ssp, userId);
}
}
break;
@@ -15312,10 +15320,10 @@
*/
@GuardedBy("this")
void tempWhitelistForPendingIntentLocked(int callerPid, int callerUid, int targetUid,
- long duration, String tag) {
+ long duration, int type, String tag) {
if (DEBUG_WHITELISTS) {
Slog.d(TAG, "tempWhitelistForPendingIntentLocked(" + callerPid + ", " + callerUid + ", "
- + targetUid + ", " + duration + ")");
+ + targetUid + ", " + duration + ", " + type + ")");
}
synchronized (mPidsSelfLocked) {
@@ -15327,7 +15335,11 @@
}
if (!pr.whitelistManager) {
if (checkPermission(CHANGE_DEVICE_IDLE_TEMP_WHITELIST, callerPid, callerUid)
- != PackageManager.PERMISSION_GRANTED) {
+ != PackageManager.PERMISSION_GRANTED
+ && checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callerPid, callerUid)
+ != PackageManager.PERMISSION_GRANTED
+ && checkPermission(START_FOREGROUND_SERVICES_FROM_BACKGROUND, callerPid,
+ callerUid) != PackageManager.PERMISSION_GRANTED) {
if (DEBUG_WHITELISTS) {
Slog.d(TAG, "tempWhitelistForPendingIntentLocked() for target " + targetUid
+ ": pid " + callerPid + " is not allowed");
@@ -15337,8 +15349,7 @@
}
}
- tempWhitelistUidLocked(targetUid, duration, tag,
- BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED);
+ tempWhitelistUidLocked(targetUid, duration, tag, type);
}
/**
@@ -15941,9 +15952,9 @@
@Override
public void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
- long duration) {
+ long duration, int type) {
mPendingIntentController.setPendingIntentWhitelistDuration(target, whitelistToken,
- duration);
+ duration, type);
}
@Override
@@ -16359,10 +16370,10 @@
@Override
public void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
- long duration, String tag) {
+ long duration, int type, String tag) {
synchronized (ActivityManagerService.this) {
ActivityManagerService.this.tempWhitelistForPendingIntentLocked(
- callerPid, callerUid, targetUid, duration, tag);
+ callerPid, callerUid, targetUid, duration, type, tag);
}
}
@@ -16716,15 +16727,27 @@
@Override
public void setDeviceOwnerUid(int uid) {
- synchronized (ActivityManagerService.this) {
- mDeviceOwnerUid = uid;
- }
+ mDeviceOwnerUid = uid;
}
@Override
public boolean isDeviceOwner(int uid) {
+ int cachedUid = mDeviceOwnerUid;
+ return uid >= 0 && cachedUid == uid;
+ }
+
+
+ @Override
+ public void setProfileOwnerUid(ArraySet<Integer> profileOwnerUids) {
synchronized (ActivityManagerService.this) {
- return uid >= 0 && mDeviceOwnerUid == uid;
+ mProfileOwnerUids = profileOwnerUids;
+ }
+ }
+
+ @Override
+ public boolean isProfileOwner(int uid) {
+ synchronized (ActivityManagerService.this) {
+ return mProfileOwnerUids != null && mProfileOwnerUids.indexOf(uid) >= 0;
}
}
@@ -16746,7 +16769,7 @@
@Override
public void addPendingTopUid(int uid, int pid) {
- mPendingStartActivityUids.add(uid, pid);
+ mPendingStartActivityUids.add(uid, pid);
}
@Override
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index 2ae3d35..42172bf 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -301,13 +301,14 @@
}
void setPendingIntentWhitelistDuration(IIntentSender target, IBinder whitelistToken,
- long duration) {
+ long duration, int type) {
if (!(target instanceof PendingIntentRecord)) {
Slog.w(TAG, "markAsSentFromNotification(): not a PendingIntentRecord: " + target);
return;
}
synchronized (mLock) {
- ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration);
+ ((PendingIntentRecord) target).setWhitelistDurationLocked(whitelistToken, duration,
+ type);
}
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index fbfed34..631b632 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -24,6 +24,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -37,6 +38,7 @@
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Pair;
import android.util.Slog;
import android.util.TimeUtils;
@@ -61,7 +63,11 @@
public final WeakReference<PendingIntentRecord> ref;
boolean sent = false;
boolean canceled = false;
- private ArrayMap<IBinder, Long> whitelistDuration;
+ /**
+ * Map IBinder to duration specified as Pair<Long, Integer>, Long is allowlist duration in
+ * milliseconds, Integer is allowlist type defined at {@link BroadcastOptions.TempAllowListType}
+ */
+ private ArrayMap<IBinder, Pair<Long, Integer>> mWhitelistDuration;
private RemoteCallbackList<IResultReceiver> mCancelCallbacks;
private ArraySet<IBinder> mAllowBgActivityStartsForActivitySender = new ArraySet<>();
private ArraySet<IBinder> mAllowBgActivityStartsForBroadcastSender = new ArraySet<>();
@@ -215,16 +221,16 @@
ref = new WeakReference<>(this);
}
- void setWhitelistDurationLocked(IBinder whitelistToken, long duration) {
+ void setWhitelistDurationLocked(IBinder whitelistToken, long duration, int type) {
if (duration > 0) {
- if (whitelistDuration == null) {
- whitelistDuration = new ArrayMap<>();
+ if (mWhitelistDuration == null) {
+ mWhitelistDuration = new ArrayMap<>();
}
- whitelistDuration.put(whitelistToken, duration);
- } else if (whitelistDuration != null) {
- whitelistDuration.remove(whitelistToken);
- if (whitelistDuration.size() <= 0) {
- whitelistDuration = null;
+ mWhitelistDuration.put(whitelistToken, new Pair(duration, type));
+ } else if (mWhitelistDuration != null) {
+ mWhitelistDuration.remove(whitelistToken);
+ if (mWhitelistDuration.size() <= 0) {
+ mWhitelistDuration = null;
}
}
@@ -292,7 +298,7 @@
if (intent != null) intent.setDefusable(true);
if (options != null) options.setDefusable(true);
- Long duration = null;
+ Pair<Long, Integer> duration = null;
Intent finalIntent = null;
Intent[] allIntents = null;
String[] allResolvedTypes = null;
@@ -341,8 +347,8 @@
mergedOptions.setCallerOptions(opts);
}
- if (whitelistDuration != null) {
- duration = whitelistDuration.get(whitelistToken);
+ if (mWhitelistDuration != null) {
+ duration = mWhitelistDuration.get(whitelistToken);
}
if (key.type == ActivityManager.INTENT_SENDER_ACTIVITY
@@ -370,24 +376,19 @@
int res = START_SUCCESS;
try {
if (duration != null) {
- int procState = controller.mAmInternal.getUidProcessState(callingUid);
- if (!ActivityManager.isProcStateBackground(procState)) {
- StringBuilder tag = new StringBuilder(64);
- tag.append("pendingintent:");
- UserHandle.formatUid(tag, callingUid);
- tag.append(":");
- if (finalIntent.getAction() != null) {
- tag.append(finalIntent.getAction());
- } else if (finalIntent.getComponent() != null) {
- finalIntent.getComponent().appendShortString(tag);
- } else if (finalIntent.getData() != null) {
- tag.append(finalIntent.getData().toSafeString());
- }
- controller.mAmInternal.tempWhitelistForPendingIntent(callingPid, callingUid,
- uid, duration, tag.toString());
- } else {
- Slog.w(TAG, "Not doing whitelist " + this + ": caller state=" + procState);
+ StringBuilder tag = new StringBuilder(64);
+ tag.append("pendingintent:");
+ UserHandle.formatUid(tag, callingUid);
+ tag.append(":");
+ if (finalIntent.getAction() != null) {
+ tag.append(finalIntent.getAction());
+ } else if (finalIntent.getComponent() != null) {
+ finalIntent.getComponent().appendShortString(tag);
+ } else if (finalIntent.getData() != null) {
+ tag.append(finalIntent.getData().toSafeString());
}
+ controller.mAmInternal.tempWhitelistForPendingIntent(callingPid, callingUid,
+ uid, duration.first, duration.second, tag.toString());
}
boolean sendFinish = finishedReceiver != null;
@@ -532,16 +533,18 @@
pw.print(prefix); pw.print("sent="); pw.print(sent);
pw.print(" canceled="); pw.println(canceled);
}
- if (whitelistDuration != null) {
+ if (mWhitelistDuration != null) {
pw.print(prefix);
pw.print("whitelistDuration=");
- for (int i = 0; i < whitelistDuration.size(); i++) {
+ for (int i = 0; i < mWhitelistDuration.size(); i++) {
if (i != 0) {
pw.print(", ");
}
- pw.print(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
+ pw.print(Integer.toHexString(System.identityHashCode(mWhitelistDuration.keyAt(i))));
pw.print(":");
- TimeUtils.formatDuration(whitelistDuration.valueAt(i), pw);
+ TimeUtils.formatDuration(mWhitelistDuration.valueAt(i).first, pw);
+ pw.print("/");
+ pw.print(mWhitelistDuration.valueAt(i).second);
}
pw.println();
}
@@ -569,15 +572,18 @@
}
sb.append(' ');
sb.append(key.typeName());
- if (whitelistDuration != null) {
+ if (mWhitelistDuration != null) {
sb.append( " (whitelist: ");
- for (int i = 0; i < whitelistDuration.size(); i++) {
+ for (int i = 0; i < mWhitelistDuration.size(); i++) {
if (i != 0) {
sb.append(",");
}
- sb.append(Integer.toHexString(System.identityHashCode(whitelistDuration.keyAt(i))));
+ sb.append(Integer.toHexString(System.identityHashCode(
+ mWhitelistDuration.keyAt(i))));
sb.append(":");
- TimeUtils.formatDuration(whitelistDuration.valueAt(i), sb);
+ TimeUtils.formatDuration(mWhitelistDuration.valueAt(i).first, sb);
+ sb.append("/");
+ sb.append(mWhitelistDuration.valueAt(i).second);
}
sb.append(")");
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 181a5cb..d4d0165 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -2078,6 +2078,13 @@
}
if (!mAllowStartFgs) {
+ // Is the calling UID a profile owner app?
+ if (mService.mInternal != null) {
+ mAllowStartFgs = mService.mInternal.isProfileOwner(info.uid);
+ }
+ }
+
+ if (!mAllowStartFgs) {
// uid is on DeviceIdleController's user/system allowlist
// or AMS's FgsStartTempAllowList.
mAllowStartFgs = mService.isWhitelistedForFgsStartLocked(info.uid);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 5d6454b..f07da8f 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -3032,8 +3032,8 @@
// This is a workaround for R QPR, new API change is not allowed. We only allow the current
// voice recognizer is also the voice interactor to noteproxy op.
- final boolean isTrustVoiceServiceProxy =
- AppOpsManager.isTrustedVoiceServiceProxy(mContext, proxyPackageName, code);
+ final boolean isTrustVoiceServiceProxy = AppOpsManager.isTrustedVoiceServiceProxy(mContext,
+ proxyPackageName, code, UserHandle.getUserId(proxyUid));
final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid;
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
@@ -3502,8 +3502,8 @@
// This is a workaround for R QPR, new API change is not allowed. We only allow the current
// voice recognizer is also the voice interactor to noteproxy op.
- final boolean isTrustVoiceServiceProxy =
- AppOpsManager.isTrustedVoiceServiceProxy(mContext, proxyPackageName, code);
+ final boolean isTrustVoiceServiceProxy = AppOpsManager.isTrustedVoiceServiceProxy(mContext,
+ proxyPackageName, code, UserHandle.getUserId(proxyUid));
final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid;
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 391a64c..17627fa 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -600,6 +600,9 @@
// caches the value returned by AudioSystem.isMicrophoneMuted()
private boolean mMicMuteFromSystemCached;
+ private boolean mFastScrollSoundEffectsEnabled;
+ private boolean mHomeSoundEffectEnabled;
+
@GuardedBy("mSettingsLock")
private int mAssistantUid;
@@ -2195,6 +2198,28 @@
caller, Binder.getCallingUid(), hasModifyAudioSettings, VOL_ADJUST_NORMAL);
}
+ public void setFastScrollSoundEffectsEnabled(boolean enabled) {
+ mFastScrollSoundEffectsEnabled = enabled;
+ }
+
+ /**
+ * @return true if the fast scroll sound effects are enabled
+ */
+ public boolean areFastScrollSoundEffectsEnabled() {
+ return mFastScrollSoundEffectsEnabled;
+ }
+
+ public void setHomeSoundEffectEnabled(boolean enabled) {
+ mHomeSoundEffectEnabled = enabled;
+ }
+
+ /**
+ * @return true if the home sound effect is enabled
+ */
+ public boolean isHomeSoundEffectEnabled() {
+ return mHomeSoundEffectEnabled;
+ }
+
private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
String callingPackage, String caller, int uid, boolean hasModifyAudioSettings,
int keyEventMode) {
@@ -8429,28 +8454,29 @@
}
for (AudioMix mix : policyConfig.getMixes()) {
// If mix is requesting privileged capture
- if (mix.getRule().allowPrivilegedPlaybackCapture()) {
- // then it must have CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT permission
- requireCaptureAudioOrMediaOutputPerm |= true;
-
- // and its format must be low quality enough
- String error = mix.canBeUsedForPrivilegedCapture(mix.getFormat());
- if (error != null) {
- Log.e(TAG, error);
+ if (mix.getRule().allowPrivilegedMediaPlaybackCapture()) {
+ // then its format must be low quality enough
+ String privilegedMediaCaptureError =
+ mix.canBeUsedForPrivilegedMediaCapture(mix.getFormat());
+ if (privilegedMediaCaptureError != null) {
+ Log.e(TAG, privilegedMediaCaptureError);
return false;
}
+ // and it must have CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT permission
+ requireCaptureAudioOrMediaOutputPerm |= true;
- // If mix is trying to excplicitly capture USAGE_VOICE_COMMUNICATION
- if (mix.containsMatchAttributeRuleForUsage(
- AudioAttributes.USAGE_VOICE_COMMUNICATION)) {
- // then it must have CAPTURE_USAGE_VOICE_COMMUNICATION_OUTPUT permission
- // Note that for UID, USERID or EXCLDUE rules, the capture will be silenced
- // in AudioPolicyMix
- if (voiceCommunicationCaptureMixes == null) {
- voiceCommunicationCaptureMixes = new ArrayList<AudioMix>();
- }
- voiceCommunicationCaptureMixes.add(mix);
+ }
+ // If mix is trying to explicitly capture USAGE_VOICE_COMMUNICATION
+ if (mix.containsMatchAttributeRuleForUsage(
+ AudioAttributes.USAGE_VOICE_COMMUNICATION)
+ && (mix.getRouteFlags() == mix.ROUTE_FLAG_LOOP_BACK_RENDER)) {
+ // It must have CAPTURE_USAGE_VOICE_COMMUNICATION_OUTPUT permission
+ // Note that for UID, USERID or EXCLDUE rules, the capture will be silenced
+ // in AudioPolicyMix
+ if (voiceCommunicationCaptureMixes == null) {
+ voiceCommunicationCaptureMixes = new ArrayList<AudioMix>();
}
+ voiceCommunicationCaptureMixes.add(mix);
}
// If mix is RENDER|LOOPBACK, then an audio MediaProjection is enough
@@ -8473,7 +8499,7 @@
if (voiceCommunicationCaptureMixes != null && voiceCommunicationCaptureMixes.size() > 0) {
if (!callerHasPermission(
android.Manifest.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT)) {
- Log.e(TAG, "Privileged audio capture for voice communication requires "
+ Log.e(TAG, "Audio capture for voice communication requires "
+ "CAPTURE_VOICE_COMMUNICATION_OUTPUT system permission");
return false;
}
diff --git a/services/core/java/com/android/server/audio/SoundEffectsHelper.java b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
index 27d5767..c14bb3e 100644
--- a/services/core/java/com/android/server/audio/SoundEffectsHelper.java
+++ b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
@@ -42,7 +42,10 @@
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* A helper class for managing sound effects loading / unloading
@@ -180,7 +183,7 @@
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build())
.build();
- loadTouchSoundAssets();
+ loadSoundAssets();
mSoundPoolLoader = new SoundPoolLoader();
mSoundPoolLoader.addHandler(new OnEffectsLoadCompleteHandler() {
@@ -316,15 +319,22 @@
return filePath;
}
- private void loadTouchSoundAssetDefaults() {
+ private void loadSoundAssetDefaults() {
int defaultResourceIdx = mResources.size();
mResources.add(new Resource("Effect_Tick.ogg"));
- for (int i = 0; i < mEffects.length; i++) {
- mEffects[i] = defaultResourceIdx;
- }
+ Arrays.fill(mEffects, defaultResourceIdx);
}
- private void loadTouchSoundAssets() {
+ /**
+ * Loads the sound assets information from audio_assets.xml
+ * The expected format of audio_assets.xml is:
+ * <ul>
+ * <li> all {@code <asset>s} listed directly in {@code <audio_assets>} </li>
+ * <li> for backwards compatibility: exactly one {@code <group>} with name
+ * {@link #GROUP_TOUCH_SOUNDS} </li>
+ * </ul>
+ */
+ private void loadSoundAssets() {
XmlResourceParser parser = null;
// only load assets once.
@@ -332,15 +342,14 @@
return;
}
- loadTouchSoundAssetDefaults();
+ loadSoundAssetDefaults();
try {
parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
String version = parser.getAttributeValue(null, ATTR_VERSION);
- boolean inTouchSoundsGroup = false;
-
+ Map<Integer, Integer> parserCounter = new HashMap<>();
if (ASSET_FILE_VERSION.equals(version)) {
while (true) {
XmlUtils.nextElement(parser);
@@ -350,19 +359,10 @@
}
if (element.equals(TAG_GROUP)) {
String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
- if (GROUP_TOUCH_SOUNDS.equals(name)) {
- inTouchSoundsGroup = true;
- break;
+ if (!GROUP_TOUCH_SOUNDS.equals(name)) {
+ Log.w(TAG, "Unsupported group name: " + name);
}
- }
- }
- while (inTouchSoundsGroup) {
- XmlUtils.nextElement(parser);
- String element = parser.getName();
- if (element == null) {
- break;
- }
- if (element.equals(TAG_ASSET)) {
+ } else if (element.equals(TAG_ASSET)) {
String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
int fx;
@@ -371,22 +371,38 @@
Field field = AudioManager.class.getField(id);
fx = field.getInt(null);
} catch (Exception e) {
- Log.w(TAG, "Invalid touch sound ID: " + id);
+ Log.w(TAG, "Invalid sound ID: " + id);
continue;
}
-
+ int currentParserCount = parserCounter.getOrDefault(fx, 0) + 1;
+ parserCounter.put(fx, currentParserCount);
+ if (currentParserCount > 1) {
+ Log.w(TAG, "Duplicate definition for sound ID: " + id);
+ }
mEffects[fx] = findOrAddResourceByFileName(file);
} else {
break;
}
}
+
+ boolean fastScrollSoundEffectsParsed = allFastScrollSoundsParsed(parserCounter);
+ boolean homeSoundParsed = parserCounter.getOrDefault(AudioManager.FX_HOME, 0) > 0;
+ if (fastScrollSoundEffectsParsed || homeSoundParsed) {
+ AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+ if (audioManager != null && fastScrollSoundEffectsParsed) {
+ audioManager.setFastScrollSoundEffectsEnabled(true);
+ }
+ if (audioManager != null && homeSoundParsed) {
+ audioManager.setHomeSoundEffectEnabled(true);
+ }
+ }
}
} catch (Resources.NotFoundException e) {
Log.w(TAG, "audio assets file not found", e);
} catch (XmlPullParserException e) {
- Log.w(TAG, "XML parser exception reading touch sound assets", e);
+ Log.w(TAG, "XML parser exception reading sound assets", e);
} catch (IOException e) {
- Log.w(TAG, "I/O exception reading touch sound assets", e);
+ Log.w(TAG, "I/O exception reading sound assets", e);
} finally {
if (parser != null) {
parser.close();
@@ -394,6 +410,15 @@
}
}
+ private boolean allFastScrollSoundsParsed(Map<Integer, Integer> parserCounter) {
+ int numFastScrollSoundEffectsParsed =
+ parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_1, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_2, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_3, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_4, 0);
+ return numFastScrollSoundEffectsParsed == AudioManager.NUM_FAST_SCROLL_SOUND_EFFECTS;
+ }
+
private int findOrAddResourceByFileName(String fileName) {
for (int i = 0; i < mResources.size(); i++) {
if (mResources.get(i).mFileName.equals(fileName)) {
diff --git a/services/core/java/com/android/server/biometrics/AuthSession.java b/services/core/java/com/android/server/biometrics/AuthSession.java
index e4d9052..52152ab 100644
--- a/services/core/java/com/android/server/biometrics/AuthSession.java
+++ b/services/core/java/com/android/server/biometrics/AuthSession.java
@@ -805,7 +805,7 @@
@Override
public String toString() {
return "State: " + mState
- + "\nisCrypto: " + isCrypto()
- + "\nPreAuthInfo: " + mPreAuthInfo;
+ + ", isCrypto: " + isCrypto()
+ + ", PreAuthInfo: " + mPreAuthInfo;
}
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricSensor.java b/services/core/java/com/android/server/biometrics/BiometricSensor.java
index 17ec112..85de81bb3 100644
--- a/services/core/java/com/android/server/biometrics/BiometricSensor.java
+++ b/services/core/java/com/android/server/biometrics/BiometricSensor.java
@@ -169,12 +169,11 @@
@Override
public String toString() {
return "ID(" + id + ")"
- + "\n oemStrength: " + oemStrength
- + "\n updatedStrength: " + mUpdatedStrength
- + "\n modality " + modality
- + "\n state: " + mSensorState
- + "\n cookie: " + mCookie
- + "\n authenticator: " + impl
- + "\n";
+ + ", oemStrength: " + oemStrength
+ + ", updatedStrength: " + mUpdatedStrength
+ + ", modality " + modality
+ + ", state: " + mSensorState
+ + ", cookie: " + mCookie
+ + ", authenticator: " + impl;
}
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index fd5ada0..3387049 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -252,12 +252,14 @@
@NonNull private final IInvalidationCallback mClientCallback;
@NonNull private final Set<Integer> mSensorsPendingInvalidation;
- public static InvalidationTracker start(@NonNull ArrayList<BiometricSensor> sensors,
+ public static InvalidationTracker start(@NonNull Context context,
+ @NonNull ArrayList<BiometricSensor> sensors,
int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
- return new InvalidationTracker(sensors, userId, fromSensorId, clientCallback);
+ return new InvalidationTracker(context, sensors, userId, fromSensorId, clientCallback);
}
- private InvalidationTracker(@NonNull ArrayList<BiometricSensor> sensors, int userId,
+ private InvalidationTracker(@NonNull Context context,
+ @NonNull ArrayList<BiometricSensor> sensors, int userId,
int fromSensorId, @NonNull IInvalidationCallback clientCallback) {
mClientCallback = clientCallback;
mSensorsPendingInvalidation = new ArraySet<>();
@@ -271,6 +273,14 @@
continue;
}
+ try {
+ if (!sensor.impl.hasEnrolledTemplates(userId, context.getOpPackageName())) {
+ continue;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote Exception", e);
+ }
+
Slog.d(TAG, "Requesting authenticatorId invalidation for sensor: " + sensor.id);
synchronized (this) {
@@ -288,6 +298,17 @@
Slog.d(TAG, "RemoteException", e);
}
}
+
+ synchronized (this) {
+ if (mSensorsPendingInvalidation.isEmpty()) {
+ try {
+ Slog.d(TAG, "No sensors require invalidation");
+ mClientCallback.onCompleted();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote Exception", e);
+ }
+ }
+ }
}
@VisibleForTesting
@@ -742,7 +763,7 @@
IInvalidationCallback callback) {
checkInternalPermission();
- InvalidationTracker.start(mSensors, userId, fromSensorId, callback);
+ InvalidationTracker.start(getContext(), mSensors, userId, fromSensorId, callback);
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 6741942..55ac248 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -52,7 +52,6 @@
import android.hardware.biometrics.SensorPropertiesInternal;
import android.os.Binder;
import android.os.Build;
-import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -62,7 +61,7 @@
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import java.util.List;
@@ -409,7 +408,7 @@
return hasPermission && keyguardPackage != null && keyguardPackage.equals(clientPackage);
}
- public static String getClientName(@Nullable ClientMonitor<?> client) {
+ public static String getClientName(@Nullable BaseClientMonitor client) {
return client != null ? client.getClass().getSimpleName() : "null";
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
index 9898d76..b3580fb 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
@@ -29,10 +29,10 @@
import android.util.Slog;
/**
- * Abstract {@link ClientMonitor} subclass that operations eligible/interested in acquisition
+ * Abstract {@link HalClientMonitor} subclass that operations eligible/interested in acquisition
* messages should extend.
*/
-public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements Interruptable {
+public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implements Interruptable {
private static final String TAG = "Biometrics/AcquisitionClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
similarity index 82%
rename from services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java
rename to services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index bbd6523..f3c37ef 100644
--- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -31,7 +31,8 @@
* the current client. Subclasses are responsible for coordinating the interaction with
* the biometric's HAL for the specific action (e.g. authenticate, enroll, enumerate, etc.).
*/
-public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinder.DeathRecipient {
+public abstract class BaseClientMonitor extends LoggableMonitor
+ implements IBinder.DeathRecipient {
private static final String TAG = "Biometrics/ClientMonitor";
protected static final boolean DEBUG = true;
@@ -49,7 +50,7 @@
*
* @param clientMonitor Reference of the ClientMonitor that is starting.
*/
- default void onClientStarted(@NonNull ClientMonitor<?> clientMonitor) {}
+ default void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {}
/**
* Invoked when the ClientMonitor operation is complete. This abstracts away asynchronous
@@ -60,22 +61,11 @@
* @param clientMonitor Reference of the ClientMonitor that finished.
* @param success True if the operation completed successfully.
*/
- default void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {}
- }
-
- /**
- * Interface that allows ClientMonitor subclasses to retrieve a fresh instance to the HAL.
- */
- public interface LazyDaemon<T> {
- /**
- * @return A fresh instance to the biometric HAL
- */
- T getDaemon();
+ default void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {}
}
protected final int mSequentialId;
@NonNull private final Context mContext;
- @NonNull protected final LazyDaemon<T> mLazyDaemon;
private final int mTargetUserId;
@NonNull private final String mOwner;
private final int mSensorId; // sensorId as configured by the framework
@@ -91,7 +81,6 @@
/**
* @param context system_server context
- * @param lazyDaemon pointer for lazy retrieval of the HAL
* @param token a unique token for the client
* @param listener recipient of related events (e.g. authentication)
* @param userId target user id for operation
@@ -102,14 +91,13 @@
* @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants
* @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants
*/
- public ClientMonitor(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
+ public BaseClientMonitor(@NonNull Context context,
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
int statsClient) {
super(statsModality, statsAction, statsClient);
mSequentialId = sCount++;
mContext = context;
- mLazyDaemon = lazyDaemon;
mToken = token;
mListener = listener;
mTargetUserId = userId;
@@ -131,15 +119,7 @@
}
/**
- * Invoked if the scheduler is unable to start the ClientMonitor (for example the HAL is null).
- * If such a problem is detected, the scheduler will not invoke
- * {@link #start(Callback)}.
- */
- public abstract void unableToStart();
-
- /**
- * Starts the ClientMonitor's lifecycle. Invokes {@link #startHalOperation()} when internal book
- * keeping is complete.
+ * Starts the ClientMonitor's lifecycle.
* @param callback invoked when the operation is complete (succeeds, fails, etc)
*/
public void start(@NonNull Callback callback) {
@@ -147,10 +127,6 @@
mCallback.onClientStarted(this);
}
- /**
- * Starts the HAL operation specific to the ClientMonitor subclass.
- */
- protected abstract void startHalOperation();
public boolean isAlreadyDone() {
return mAlreadyDone;
@@ -219,10 +195,6 @@
return mSensorId;
}
- public T getFreshDaemon() {
- return mLazyDaemon.getDaemon();
- }
-
@Override
public String toString() {
return "{[" + mSequentialId + "] "
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index b430521..aa7faf5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -44,8 +44,8 @@
import java.util.Locale;
/**
- * A scheduler for biometric HAL operations. Maintains a queue of {@link ClientMonitor} operations,
- * without caring about its implementation details. Operations may perform one or more
+ * A scheduler for biometric HAL operations. Maintains a queue of {@link BaseClientMonitor}
+ * operations, without caring about its implementation details. Operations may perform one or more
* interactions with the HAL before finishing.
*/
public class BiometricScheduler {
@@ -88,7 +88,7 @@
static final int STATE_WAITING_FOR_COOKIE = 4;
/**
- * The {@link ClientMonitor.Callback} has been invoked and the client is finished.
+ * The {@link BaseClientMonitor.Callback} has been invoked and the client is finished.
*/
static final int STATE_FINISHED = 5;
@@ -101,20 +101,37 @@
@Retention(RetentionPolicy.SOURCE)
@interface OperationState {}
- @NonNull final ClientMonitor<?> clientMonitor;
- @Nullable final ClientMonitor.Callback mClientCallback;
- @OperationState int state;
+ @NonNull final BaseClientMonitor mClientMonitor;
+ @Nullable final BaseClientMonitor.Callback mClientCallback;
+ @OperationState int mState;
- Operation(@NonNull ClientMonitor<?> clientMonitor,
- @Nullable ClientMonitor.Callback callback) {
- this.clientMonitor = clientMonitor;
+ Operation(@NonNull BaseClientMonitor clientMonitor,
+ @Nullable BaseClientMonitor.Callback callback) {
+ this.mClientMonitor = clientMonitor;
this.mClientCallback = callback;
- state = STATE_WAITING_IN_QUEUE;
+ mState = STATE_WAITING_IN_QUEUE;
+ }
+
+ public boolean isHalOperation() {
+ return mClientMonitor instanceof HalClientMonitor<?>;
+ }
+
+ /**
+ * @return true if the operation requires the HAL, and the HAL is null.
+ */
+ public boolean isUnstartableHalOperation() {
+ if (isHalOperation()) {
+ final HalClientMonitor<?> client = (HalClientMonitor<?>) mClientMonitor;
+ if (client.getFreshDaemon() == null) {
+ return true;
+ }
+ }
+ return false;
}
@Override
public String toString() {
- return clientMonitor + ", State: " + state;
+ return mClientMonitor + ", State: " + mState;
}
}
@@ -134,10 +151,10 @@
@Override
public void run() {
- if (operation.state != Operation.STATE_FINISHED) {
+ if (operation.mState != Operation.STATE_FINISHED) {
Slog.e(tag, "[Watchdog Triggered]: " + operation);
- operation.clientMonitor.mCallback
- .onClientFinished(operation.clientMonitor, false /* success */);
+ operation.mClientMonitor.mCallback
+ .onClientFinished(operation.mClientMonitor, false /* success */);
}
}
}
@@ -186,9 +203,9 @@
// Internal callback, notified when an operation is complete. Notifies the requester
// that the operation is complete, before performing internal scheduler work (such as
// starting the next client).
- public class InternalCallback implements ClientMonitor.Callback {
+ public class InternalCallback implements BaseClientMonitor.Callback {
@Override
- public void onClientStarted(@NonNull ClientMonitor<?> clientMonitor) {
+ public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
Slog.d(getTag(), "[Started] " + clientMonitor);
if (mCurrentOperation.mClientCallback != null) {
mCurrentOperation.mClientCallback.onClientStarted(clientMonitor);
@@ -196,7 +213,7 @@
}
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
mHandler.post(() -> {
if (mCurrentOperation == null) {
Slog.e(getTag(), "[Finishing] " + clientMonitor
@@ -205,14 +222,14 @@
return;
}
- if (clientMonitor != mCurrentOperation.clientMonitor) {
+ if (clientMonitor != mCurrentOperation.mClientMonitor) {
Slog.e(getTag(), "[Ignoring Finish] " + clientMonitor + " does not match"
- + " current: " + mCurrentOperation.clientMonitor);
+ + " current: " + mCurrentOperation.mClientMonitor);
return;
}
Slog.d(getTag(), "[Finishing] " + clientMonitor + ", success: " + success);
- mCurrentOperation.state = Operation.STATE_FINISHED;
+ mCurrentOperation.mState = Operation.STATE_FINISHED;
if (mCurrentOperation.mClientCallback != null) {
mCurrentOperation.mClientCallback.onClientFinished(clientMonitor, success);
@@ -220,7 +237,7 @@
if (mGestureAvailabilityDispatcher != null) {
mGestureAvailabilityDispatcher.markSensorActive(
- mCurrentOperation.clientMonitor.getSensorId(), false /* active */);
+ mCurrentOperation.mClientMonitor.getSensorId(), false /* active */);
}
mCurrentOperation = null;
@@ -276,11 +293,11 @@
}
mCurrentOperation = mPendingOperations.poll();
- final ClientMonitor<?> currentClient = mCurrentOperation.clientMonitor;
+ final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor;
// If the operation at the front of the queue has been marked for cancellation, send
// ERROR_CANCELED. No need to start this client.
- if (mCurrentOperation.state == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
+ if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
Slog.d(getTag(), "[Now Cancelling] " + mCurrentOperation);
if (!(currentClient instanceof Interruptable)) {
throw new IllegalStateException("Mis-implemented client or scheduler, "
@@ -295,9 +312,9 @@
}
if (mGestureAvailabilityDispatcher != null
- && mCurrentOperation.clientMonitor instanceof AcquisitionClient) {
+ && mCurrentOperation.mClientMonitor instanceof AcquisitionClient) {
mGestureAvailabilityDispatcher.markSensorActive(
- mCurrentOperation.clientMonitor.getSensorId(),
+ mCurrentOperation.mClientMonitor.getSensorId(),
true /* active */);
}
@@ -305,7 +322,9 @@
// to arrive at the head of the queue, before pinging it to start.
final boolean shouldStartNow = currentClient.getCookie() == 0;
if (shouldStartNow) {
- if (mCurrentOperation.clientMonitor.getFreshDaemon() == null) {
+ if (mCurrentOperation.isUnstartableHalOperation()) {
+ final HalClientMonitor<?> halClientMonitor =
+ (HalClientMonitor<?>) mCurrentOperation.mClientMonitor;
// Note down current length of queue
final int pendingOperationsLength = mPendingOperations.size();
final Operation lastOperation = mPendingOperations.peekLast();
@@ -315,10 +334,10 @@
// For current operations, 1) unableToStart, which notifies the caller-side, then
// 2) notify operation's callback, to notify applicable system service that the
// operation failed.
- mCurrentOperation.clientMonitor.unableToStart();
+ halClientMonitor.unableToStart();
if (mCurrentOperation.mClientCallback != null) {
- mCurrentOperation.mClientCallback
- .onClientFinished(mCurrentOperation.clientMonitor, false /* success */);
+ mCurrentOperation.mClientCallback.onClientFinished(
+ mCurrentOperation.mClientMonitor, false /* success */);
}
// Then for each operation currently in the pending queue at the time of this
@@ -331,9 +350,11 @@
+ ", expected length: " + pendingOperationsLength);
break;
}
- operation.clientMonitor.unableToStart();
+ if (operation.isHalOperation()) {
+ ((HalClientMonitor<?>) operation.mClientMonitor).unableToStart();
+ }
if (operation.mClientCallback != null) {
- operation.mClientCallback.onClientFinished(operation.clientMonitor,
+ operation.mClientCallback.onClientFinished(operation.mClientMonitor,
false /* success */);
}
Slog.w(getTag(), "[Aborted Operation] " + operation);
@@ -347,7 +368,7 @@
} else {
Slog.d(getTag(), "[Starting] " + mCurrentOperation);
currentClient.start(getInternalCallback());
- mCurrentOperation.state = Operation.STATE_STARTED;
+ mCurrentOperation.mState = Operation.STATE_STARTED;
}
} else {
try {
@@ -356,7 +377,7 @@
Slog.e(getTag(), "Remote exception when contacting BiometricService", e);
}
Slog.d(getTag(), "Waiting for cookie before starting: " + mCurrentOperation);
- mCurrentOperation.state = Operation.STATE_WAITING_FOR_COOKIE;
+ mCurrentOperation.mState = Operation.STATE_WAITING_FOR_COOKIE;
}
}
@@ -378,13 +399,14 @@
Slog.e(getTag(), "Current operation is null");
return;
}
- if (mCurrentOperation.state != Operation.STATE_WAITING_FOR_COOKIE) {
- if (mCurrentOperation.state == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
+ if (mCurrentOperation.mState != Operation.STATE_WAITING_FOR_COOKIE) {
+ if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
Slog.d(getTag(), "Operation was marked for cancellation, cancelling now: "
+ mCurrentOperation);
// This should trigger the internal onClientFinished callback, which clears the
// operation and starts the next one.
- final Interruptable interruptable = (Interruptable) mCurrentOperation.clientMonitor;
+ final Interruptable interruptable =
+ (Interruptable) mCurrentOperation.mClientMonitor;
interruptable.onError(BiometricConstants.BIOMETRIC_ERROR_CANCELED,
0 /* vendorCode */);
return;
@@ -394,55 +416,57 @@
return;
}
}
- if (mCurrentOperation.clientMonitor.getCookie() != cookie) {
+ if (mCurrentOperation.mClientMonitor.getCookie() != cookie) {
Slog.e(getTag(), "Mismatched cookie for operation: " + mCurrentOperation
+ ", received: " + cookie);
return;
}
- if (mCurrentOperation.clientMonitor.getFreshDaemon() == null) {
+ if (mCurrentOperation.isUnstartableHalOperation()) {
Slog.e(getTag(), "[Unable To Start] Prepared client: " + mCurrentOperation);
// This is BiometricPrompt trying to auth but something's wrong with the HAL.
- mCurrentOperation.clientMonitor.unableToStart();
+ final HalClientMonitor<?> halClientMonitor =
+ (HalClientMonitor<?>) mCurrentOperation.mClientMonitor;
+ halClientMonitor.unableToStart();
if (mCurrentOperation.mClientCallback != null) {
- mCurrentOperation.mClientCallback.onClientFinished(mCurrentOperation.clientMonitor,
+ mCurrentOperation.mClientCallback.onClientFinished(mCurrentOperation.mClientMonitor,
false /* success */);
}
mCurrentOperation = null;
startNextOperationIfIdle();
} else {
Slog.d(getTag(), "[Starting] Prepared client: " + mCurrentOperation);
- mCurrentOperation.state = Operation.STATE_STARTED;
- mCurrentOperation.clientMonitor.start(getInternalCallback());
+ mCurrentOperation.mState = Operation.STATE_STARTED;
+ mCurrentOperation.mClientMonitor.start(getInternalCallback());
}
}
/**
- * Adds a {@link ClientMonitor} to the pending queue
+ * Adds a {@link BaseClientMonitor} to the pending queue
*
* @param clientMonitor operation to be scheduled
*/
- public void scheduleClientMonitor(@NonNull ClientMonitor<?> clientMonitor) {
+ public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor) {
scheduleClientMonitor(clientMonitor, null /* clientFinishCallback */);
}
/**
- * Adds a {@link ClientMonitor} to the pending queue
+ * Adds a {@link BaseClientMonitor} to the pending queue
*
* @param clientMonitor operation to be scheduled
* @param clientCallback optional callback, invoked when the client is finished, but
* before it has been removed from the queue.
*/
- public void scheduleClientMonitor(@NonNull ClientMonitor<?> clientMonitor,
- @Nullable ClientMonitor.Callback clientCallback) {
+ public void scheduleClientMonitor(@NonNull BaseClientMonitor clientMonitor,
+ @Nullable BaseClientMonitor.Callback clientCallback) {
// Mark any interruptable pending clients as canceling. Once they reach the head of the
// queue, the scheduler will send ERROR_CANCELED and skip the operation.
for (Operation operation : mPendingOperations) {
- if (operation.clientMonitor instanceof Interruptable
- && operation.state != Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
+ if (operation.mClientMonitor instanceof Interruptable
+ && operation.mState != Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
Slog.d(getTag(), "New client incoming, marking pending client as canceling: "
- + operation.clientMonitor);
- operation.state = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
+ + operation.mClientMonitor);
+ operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
}
}
@@ -451,8 +475,8 @@
+ ", new queue size: " + mPendingOperations.size());
// If the current operation is cancellable, start the cancellation process.
- if (mCurrentOperation != null && mCurrentOperation.clientMonitor instanceof Interruptable
- && mCurrentOperation.state == Operation.STATE_STARTED) {
+ if (mCurrentOperation != null && mCurrentOperation.mClientMonitor instanceof Interruptable
+ && mCurrentOperation.mState == Operation.STATE_STARTED) {
Slog.d(getTag(), "[Cancelling Interruptable]: " + mCurrentOperation);
cancelInternal(mCurrentOperation);
}
@@ -465,25 +489,25 @@
Slog.e(getTag(), "cancelInternal invoked on non-current operation: " + operation);
return;
}
- if (!(operation.clientMonitor instanceof Interruptable)) {
+ if (!(operation.mClientMonitor instanceof Interruptable)) {
Slog.w(getTag(), "Operation not interruptable: " + operation);
return;
}
- if (operation.state == Operation.STATE_STARTED_CANCELING) {
+ if (operation.mState == Operation.STATE_STARTED_CANCELING) {
Slog.w(getTag(), "Cancel already invoked for operation: " + operation);
return;
}
- if (operation.state == Operation.STATE_WAITING_FOR_COOKIE) {
+ if (operation.mState == Operation.STATE_WAITING_FOR_COOKIE) {
Slog.w(getTag(), "Skipping cancellation for non-started operation: " + operation);
// We can set it to null immediately, since the HAL was never notified to start.
mCurrentOperation = null;
startNextOperationIfIdle();
return;
}
- Slog.d(getTag(), "[Cancelling] Current client: " + operation.clientMonitor);
- final Interruptable interruptable = (Interruptable) operation.clientMonitor;
+ Slog.d(getTag(), "[Cancelling] Current client: " + operation.mClientMonitor);
+ final Interruptable interruptable = (Interruptable) operation.mClientMonitor;
interruptable.cancel();
- operation.state = Operation.STATE_STARTED_CANCELING;
+ operation.mState = Operation.STATE_STARTED_CANCELING;
// Add a watchdog. If the HAL does not acknowledge within the timeout, we will
// forcibly finish this client.
@@ -500,8 +524,8 @@
Slog.e(getTag(), "Unable to cancel enrollment, null operation");
return;
}
- final boolean isEnrolling = mCurrentOperation.clientMonitor instanceof EnrollClient;
- final boolean tokenMatches = mCurrentOperation.clientMonitor.getToken() == token;
+ final boolean isEnrolling = mCurrentOperation.mClientMonitor instanceof EnrollClient;
+ final boolean tokenMatches = mCurrentOperation.mClientMonitor.getToken() == token;
if (!isEnrolling || !tokenMatches) {
Slog.w(getTag(), "Not cancelling enrollment, isEnrolling: " + isEnrolling
+ " tokenMatches: " + tokenMatches);
@@ -521,8 +545,8 @@
return;
}
final boolean isAuthenticating =
- mCurrentOperation.clientMonitor instanceof AuthenticationConsumer;
- final boolean tokenMatches = mCurrentOperation.clientMonitor.getToken() == token;
+ mCurrentOperation.mClientMonitor instanceof AuthenticationConsumer;
+ final boolean tokenMatches = mCurrentOperation.mClientMonitor.getToken() == token;
if (!isAuthenticating || !tokenMatches) {
Slog.w(getTag(), "Not cancelling authentication"
+ ", current operation : " + mCurrentOperation
@@ -536,11 +560,11 @@
/**
* @return the current operation
*/
- public ClientMonitor<?> getCurrentClient() {
+ public BaseClientMonitor getCurrentClient() {
if (mCurrentOperation == null) {
return null;
}
- return mCurrentOperation.clientMonitor;
+ return mCurrentOperation.mClientMonitor;
}
public int getCurrentPendingCount() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/EnumerateConsumer.java b/services/core/java/com/android/server/biometrics/sensors/EnumerateConsumer.java
index 8ad9e6a..07a4d11 100644
--- a/services/core/java/com/android/server/biometrics/sensors/EnumerateConsumer.java
+++ b/services/core/java/com/android/server/biometrics/sensors/EnumerateConsumer.java
@@ -19,8 +19,8 @@
import android.hardware.biometrics.BiometricAuthenticator;
/**
- * Interface that {@link ClientMonitor} subclasses eligible/interested in enumerate callbacks should
- * implement.
+ * Interface that {@link BaseClientMonitor} subclasses eligible/interested in enumerate callbacks
+ * should implement.
*/
public interface EnumerateConsumer {
/**
diff --git a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
index bac944f..6a622c3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
@@ -23,7 +23,7 @@
import android.os.RemoteException;
import android.util.Slog;
-public abstract class GenerateChallengeClient<T> extends ClientMonitor<T> {
+public abstract class GenerateChallengeClient<T> extends HalClientMonitor<T> {
private static final String TAG = "GenerateChallengeClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
new file mode 100644
index 0000000..63cd412
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.biometrics.BiometricsProtoEnums;
+import android.os.IBinder;
+
+/**
+ * Abstract {@link BaseClientMonitor} implementation that supports HAL operations.
+ * @param <T> HAL template
+ */
+public abstract class HalClientMonitor<T> extends BaseClientMonitor {
+ /**
+ * Interface that allows ClientMonitor subclasses to retrieve a fresh instance to the HAL.
+ */
+ public interface LazyDaemon<T> {
+ /**
+ * @return A fresh instance to the biometric HAL
+ */
+ T getDaemon();
+ }
+
+ /**
+ * Starts the HAL operation specific to the ClientMonitor subclass.
+ */
+ protected abstract void startHalOperation();
+
+ /**
+ * Invoked if the scheduler is unable to start the ClientMonitor (for example the HAL is null).
+ * If such a problem is detected, the scheduler will not invoke
+ * {@link #start(Callback)}.
+ */
+ public abstract void unableToStart();
+
+ @NonNull
+ protected final LazyDaemon<T> mLazyDaemon;
+
+ /**
+ * @param context system_server context
+ * @param lazyDaemon pointer for lazy retrieval of the HAL
+ * @param token a unique token for the client
+ * @param listener recipient of related events (e.g. authentication)
+ * @param userId target user id for operation
+ * @param owner name of the client that owns this
+ * @param cookie BiometricPrompt authentication cookie (to be moved into a subclass soon)
+ * @param sensorId ID of the sensor that the operation should be requested of
+ * @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants
+ * @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants
+ * @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants
+ */
+ public HalClientMonitor(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
+ @Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
+ @NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
+ int statsClient) {
+ super(context, token, listener, userId, owner, cookie, sensorId, statsModality,
+ statsAction, statsClient);
+ mLazyDaemon = lazyDaemon;
+ }
+
+ @Nullable
+ public T getFreshDaemon() {
+ return mLazyDaemon.getDaemon();
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index e738d17..8529e81 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -39,7 +39,7 @@
* {@link #onRemoved(BiometricAuthenticator.Identifier, int)} returns true/
*/
public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Identifier, T>
- extends ClientMonitor<T> implements EnumerateConsumer, RemovalConsumer {
+ extends HalClientMonitor<T> implements EnumerateConsumer, RemovalConsumer {
private static final String TAG = "Biometrics/InternalCleanupClient";
@@ -60,11 +60,11 @@
private final BiometricUtils<S> mBiometricUtils;
private final Map<Integer, Long> mAuthenticatorIds;
private final List<S> mEnrolledList;
- private ClientMonitor<T> mCurrentTask;
+ private BaseClientMonitor mCurrentTask;
private final Callback mEnumerateCallback = new Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
final List<BiometricAuthenticator.Identifier> unknownHALTemplates =
((InternalEnumerateClient<T>) mCurrentTask).getUnknownHALTemplates();
@@ -88,7 +88,7 @@
private final Callback mRemoveCallback = new Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
mCallback.onClientFinished(InternalCleanupClient.this, success);
}
};
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
index e07f712..2693f2f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
@@ -31,7 +31,7 @@
/**
* Internal class to help clean up unknown templates in the HAL and Framework
*/
-public abstract class InternalEnumerateClient<T> extends ClientMonitor<T>
+public abstract class InternalEnumerateClient<T> extends HalClientMonitor<T>
implements EnumerateConsumer {
private static final String TAG = "Biometrics/InternalEnumerateClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/Interruptable.java b/services/core/java/com/android/server/biometrics/sensors/Interruptable.java
index 28e0117..70d9b26 100644
--- a/services/core/java/com/android/server/biometrics/sensors/Interruptable.java
+++ b/services/core/java/com/android/server/biometrics/sensors/Interruptable.java
@@ -19,7 +19,7 @@
import android.annotation.NonNull;
/**
- * Interface that {@link ClientMonitor} subclasses eligible/interested in error callbacks should
+ * Interface that {@link BaseClientMonitor} subclasses eligible/interested in error callbacks should
* implement.
*/
public interface Interruptable {
@@ -37,10 +37,10 @@
/**
* Notifies the client that it needs to finish before
- * {@link ClientMonitor#start(ClientMonitor.Callback)} was invoked. This usually happens
+ * {@link BaseClientMonitor#start(BaseClientMonitor.Callback)} was invoked. This usually happens
* if the client is still waiting in the pending queue and got notified that a subsequent
* operation is preempting it.
* @param callback invoked when the operation is completed.
*/
- void cancelWithoutStarting(@NonNull ClientMonitor.Callback callback);
+ void cancelWithoutStarting(@NonNull BaseClientMonitor.Callback callback);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java b/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java
index fe946cb..630e5ea 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java
@@ -20,6 +20,9 @@
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.IInvalidationCallback;
+import android.os.RemoteException;
+import android.util.Slog;
import java.util.Map;
@@ -28,24 +31,31 @@
* {@link InvalidationRequesterClient} for more info.
*/
public abstract class InvalidationClient<S extends BiometricAuthenticator.Identifier, T>
- extends ClientMonitor<T> {
+ extends HalClientMonitor<T> {
- private final BiometricUtils<S> mUtils;
- private final Map<Integer, Long> mAuthenticatorIds;
+ private static final String TAG = "InvalidationClient";
+
+ @NonNull private final Map<Integer, Long> mAuthenticatorIds;
+ @NonNull private final IInvalidationCallback mInvalidationCallback;
public InvalidationClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
- int userId, int sensorId, @NonNull BiometricUtils<S> utils,
- @NonNull Map<Integer, Long> authenticatorIds) {
+ int userId, int sensorId, @NonNull Map<Integer, Long> authenticatorIds,
+ @NonNull IInvalidationCallback callback) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId,
context.getOpPackageName(), 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN);
- mUtils = utils;
mAuthenticatorIds = authenticatorIds;
+ mInvalidationCallback = callback;
}
public void onAuthenticatorIdInvalidated(long newAuthenticatorId) {
mAuthenticatorIds.put(getTargetUserId(), newAuthenticatorId);
+ try {
+ mInvalidationCallback.onCompleted();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
mCallback.onClientFinished(this, true /* success */);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java b/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java
index d95fa23..c97003b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java
@@ -55,8 +55,8 @@
* switches, the framework can check if any sensor has the "invalidationInProgress" flag set. If so,
* the framework should re-start the invalidation process described above.
*/
-public abstract class InvalidationRequesterClient<S extends BiometricAuthenticator.Identifier, T>
- extends ClientMonitor<T> {
+public class InvalidationRequesterClient<S extends BiometricAuthenticator.Identifier>
+ extends BaseClientMonitor {
private final BiometricManager mBiometricManager;
@NonNull private final BiometricUtils<S> mUtils;
@@ -71,9 +71,9 @@
}
};
- public InvalidationRequesterClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
- int userId, int sensorId, @NonNull BiometricUtils<S> utils) {
- super(context, lazyDaemon, null /* token */, null /* listener */, userId,
+ public InvalidationRequesterClient(@NonNull Context context, int userId, int sensorId,
+ @NonNull BiometricUtils<S> utils) {
+ super(context, null /* token */, null /* listener */, userId,
context.getOpPackageName(), 0 /* cookie */, sensorId,
BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
BiometricsProtoEnums.CLIENT_UNKNOWN);
@@ -89,14 +89,4 @@
mBiometricManager.invalidateAuthenticatorIds(getTargetUserId(), getSensorId(),
mInvalidationCallback);
}
-
- @Override
- public void unableToStart() {
-
- }
-
- @Override
- protected void startHalOperation() {
- // No HAL operations necessary
- }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
index f79abd5..4ea48fd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
@@ -31,7 +31,7 @@
* A class to keep track of the remove state for a given client.
*/
public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier, T>
- extends ClientMonitor<T> implements RemovalConsumer {
+ extends HalClientMonitor<T> implements RemovalConsumer {
private static final String TAG = "Biometrics/RemovalClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalConsumer.java b/services/core/java/com/android/server/biometrics/sensors/RemovalConsumer.java
index 0aba7e4..82fa1647a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RemovalConsumer.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RemovalConsumer.java
@@ -20,8 +20,8 @@
import android.hardware.biometrics.BiometricAuthenticator;
/**
- * Interface that {@link ClientMonitor} subclasses eligible/interested in removal callbacks should
- * implement.
+ * Interface that {@link BaseClientMonitor} subclasses eligible/interested in removal callbacks
+ * should implement.
*/
public interface RemovalConsumer {
/**
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 5deb8fa..187193d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
@@ -21,7 +21,7 @@
import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
-public abstract class RevokeChallengeClient<T> extends ClientMonitor<T> {
+public abstract class RevokeChallengeClient<T> extends HalClientMonitor<T> {
public RevokeChallengeClient(@NonNull Context context, @NonNull LazyDaemon<T> lazyDaemon,
@NonNull IBinder token, @NonNull String owner, int sensorId) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
index c27b6e5..5fb194c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
@@ -23,11 +23,11 @@
import android.os.RemoteException;
import android.util.Slog;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import java.util.Map;
-class FaceGetAuthenticatorIdClient extends ClientMonitor<ISession> {
+class FaceGetAuthenticatorIdClient extends HalClientMonitor<ISession> {
private static final String TAG = "FaceGetAuthenticatorIdClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java
index 9c6438e..855ee1d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java
@@ -18,13 +18,13 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.face.ISession;
import android.hardware.face.Face;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.InvalidationClient;
-import com.android.server.biometrics.sensors.face.FaceUtils;
import java.util.Map;
@@ -33,8 +33,8 @@
public FaceInvalidationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, int userId, int sensorId,
- @NonNull FaceUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
- super(context, lazyDaemon, userId, sensorId, utils, authenticatorIds);
+ @NonNull Map<Integer, Long> authenticatorIds, @NonNull IInvalidationCallback callback) {
+ super(context, lazyDaemon, userId, sensorId, authenticatorIds, callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index cec1cb8..810489b1c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -20,10 +20,10 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
-import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
@@ -44,8 +44,10 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AuthenticationClient;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.HalClientMonitor;
+import com.android.server.biometrics.sensors.InvalidationRequesterClient;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.PerformanceTracker;
import com.android.server.biometrics.sensors.face.FaceUtils;
@@ -73,7 +75,7 @@
@NonNull private final String mHalInstanceName;
@NonNull @VisibleForTesting
final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
- @NonNull private final ClientMonitor.LazyDaemon<IFace> mLazyDaemon;
+ @NonNull private final HalClientMonitor.LazyDaemon<IFace> mLazyDaemon;
@NonNull private final Handler mHandler;
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
@NonNull private final UsageStats mUsageStats;
@@ -87,7 +89,7 @@
public void onTaskStackChanged() {
mHandler.post(() -> {
for (int i = 0; i < mSensors.size(); i++) {
- final ClientMonitor<?> client = mSensors.valueAt(i).getScheduler()
+ final BaseClientMonitor client = mSensors.valueAt(i).getScheduler()
.getCurrentClient();
if (!(client instanceof AuthenticationClient)) {
Slog.e(getTag(), "Task stack changed for client: " + client);
@@ -181,7 +183,7 @@
return mDaemon;
}
- private void scheduleForSensor(int sensorId, @NonNull ClientMonitor<?> client) {
+ private void scheduleForSensor(int sensorId, @NonNull BaseClientMonitor client) {
if (!mSensors.contains(sensorId)) {
throw new IllegalStateException("Unable to schedule client: " + client
+ " for sensor: " + sensorId);
@@ -189,8 +191,8 @@
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
}
- private void scheduleForSensor(int sensorId, @NonNull ClientMonitor<?> client,
- ClientMonitor.Callback callback) {
+ private void scheduleForSensor(int sensorId, @NonNull BaseClientMonitor client,
+ BaseClientMonitor.Callback callback) {
if (!mSensors.contains(sensorId)) {
throw new IllegalStateException("Unable to schedule client: " + client
+ " for sensor: " + sensorId);
@@ -205,6 +207,12 @@
// this method "withoutHandler" means it should only ever be invoked from the worker thread,
// so callers will never be blocked.
mSensors.get(sensorId).createNewSession(daemon, sensorId, userId);
+
+ if (FaceUtils.getInstance(sensorId).isInvalidationInProgress(mContext, userId)) {
+ Slog.w(getTag(), "Scheduling unfinished invalidation request for sensor: " + sensorId
+ + ", user: " + userId);
+ scheduleInvalidationRequest(sensorId, userId);
+ }
}
@@ -241,6 +249,15 @@
});
}
+ private void scheduleInvalidationRequest(int sensorId, int userId) {
+ mHandler.post(() -> {
+ final InvalidationRequesterClient<Face> client =
+ new InvalidationRequesterClient<>(mContext, userId, sensorId,
+ FaceUtils.getInstance(sensorId));
+ mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+ });
+ }
+
@Override
public boolean containsSensor(int sensorId) {
return mSensors.contains(sensorId);
@@ -269,6 +286,32 @@
}
@Override
+ public void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
+ @NonNull IInvalidationCallback callback) {
+ mHandler.post(() -> {
+ final IFace daemon = getHalInstance();
+ if (daemon == null) {
+ Slog.e(getTag(), "Null daemon during scheduleInvalidateAuthenticatorId: "
+ + sensorId);
+ return;
+ }
+
+ try {
+ if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
+ createNewSessionWithoutHandler(daemon, sensorId, userId);
+ }
+
+ final FaceInvalidationClient client = new FaceInvalidationClient(mContext,
+ mSensors.get(sensorId).getLazySession(), userId, sensorId,
+ mSensors.get(sensorId).getAuthenticatorIds(), callback);
+ mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+ } catch (RemoteException e) {
+ Slog.e(getTag(), "Remote exception", e);
+ }
+ });
+ }
+
+ @Override
public int getLockoutModeForUser(int sensorId, int userId) {
return mSensors.get(sensorId).getLockoutCache().getLockoutModeForUser(userId);
}
@@ -362,12 +405,13 @@
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, FaceUtils.getInstance(sensorId), disabledFeatures,
ENROLL_TIMEOUT_SEC, previewSurface, sensorId, maxTemplatesPerUser);
- scheduleForSensor(sensorId, client, new ClientMonitor.Callback() {
+ scheduleForSensor(sensorId, client, new BaseClientMonitor.Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor,
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
if (success) {
scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
+ scheduleInvalidationRequest(sensorId, userId);
}
}
});
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
index 5b1f546..f355158 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
@@ -26,7 +26,7 @@
import android.util.Slog;
import com.android.server.biometrics.HardwareAuthTokenUtils;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
@@ -36,7 +36,7 @@
* Updates the framework's lockout cache and notifies clients such as Keyguard when lockout is
* cleared.
*/
-public class FaceResetLockoutClient extends ClientMonitor<ISession> {
+public class FaceResetLockoutClient extends HalClientMonitor<ISession> {
private static final String TAG = "FaceResetLockoutClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index f9e3106..82ad387 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -45,9 +45,10 @@
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.EnumerateConsumer;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.Interruptable;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutConsumer;
@@ -73,7 +74,7 @@
@NonNull private final BiometricScheduler mScheduler;
@NonNull private final LockoutCache mLockoutCache;
@NonNull private final Map<Integer, Long> mAuthenticatorIds;
- @NonNull private final ClientMonitor.LazyDaemon<ISession> mLazySession;
+ @NonNull private final HalClientMonitor.LazyDaemon<ISession> mLazySession;
@Nullable private Session mCurrentSession;
static class Session {
@@ -136,7 +137,7 @@
@Override
public void onChallengeGenerated(long challenge) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FaceGenerateChallengeClient)) {
Slog.e(mTag, "onChallengeGenerated for wrong client: "
+ Utils.getClientName(client));
@@ -152,7 +153,7 @@
@Override
public void onChallengeRevoked(long challenge) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FaceRevokeChallengeClient)) {
Slog.e(mTag, "onChallengeRevoked for wrong client: "
+ Utils.getClientName(client));
@@ -168,7 +169,7 @@
@Override
public void onAcquired(byte info, int vendorCode) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AcquisitionClient)) {
Slog.e(mTag, "onAcquired for non-acquisition client: "
+ Utils.getClientName(client));
@@ -183,7 +184,7 @@
@Override
public void onError(byte error, int vendorCode) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
Slog.d(mTag, "onError"
+ ", client: " + Utils.getClientName(client)
+ ", error: " + error
@@ -206,7 +207,7 @@
@Override
public void onEnrollmentProgress(int enrollmentId, int remaining) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FaceEnrollClient)) {
Slog.e(mTag, "onEnrollmentProgress for non-enroll client: "
+ Utils.getClientName(client));
@@ -226,7 +227,7 @@
@Override
public void onAuthenticationSucceeded(int enrollmentId, HardwareAuthToken hat) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(mTag, "onAuthenticationSucceeded for non-authentication consumer: "
+ Utils.getClientName(client));
@@ -248,7 +249,7 @@
@Override
public void onAuthenticationFailed() {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(mTag, "onAuthenticationFailed for non-authentication consumer: "
+ Utils.getClientName(client));
@@ -266,7 +267,7 @@
@Override
public void onLockoutTimed(long durationMillis) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof LockoutConsumer)) {
Slog.e(mTag, "onLockoutTimed for non-lockout consumer: "
+ Utils.getClientName(client));
@@ -281,7 +282,7 @@
@Override
public void onLockoutPermanent() {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof LockoutConsumer)) {
Slog.e(mTag, "onLockoutPermanent for non-lockout consumer: "
+ Utils.getClientName(client));
@@ -296,7 +297,7 @@
@Override
public void onLockoutCleared() {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FaceResetLockoutClient)) {
Slog.e(mTag, "onLockoutCleared for non-resetLockout client: "
+ Utils.getClientName(client));
@@ -316,7 +317,7 @@
@Override
public void onEnrollmentsEnumerated(int[] enrollmentIds) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof EnumerateConsumer)) {
Slog.e(mTag, "onEnrollmentsEnumerated for non-enumerate consumer: "
+ Utils.getClientName(client));
@@ -339,7 +340,7 @@
@Override
public void onEnrollmentsRemoved(int[] enrollmentIds) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof RemovalConsumer)) {
Slog.e(mTag, "onRemoved for non-removal consumer: "
+ Utils.getClientName(client));
@@ -361,7 +362,7 @@
@Override
public void onAuthenticatorIdRetrieved(long authenticatorId) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FaceGetAuthenticatorIdClient)) {
Slog.e(mTag, "onAuthenticatorIdRetrieved for wrong consumer: "
+ Utils.getClientName(client));
@@ -376,7 +377,17 @@
@Override
public void onAuthenticatorIdInvalidated(long newAuthenticatorId) {
- // TODO(b/159667191)
+ mHandler.post(() -> {
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
+ if (!(client instanceof FaceInvalidationClient)) {
+ Slog.e(mTag, "onAuthenticatorIdInvalidated for wrong consumer: "
+ + Utils.getClientName(client));
+ return;
+ }
+
+ final FaceInvalidationClient invalidationClient = (FaceInvalidationClient) client;
+ invalidationClient.onAuthenticatorIdInvalidated(newAuthenticatorId);
+ });
}
}
@@ -400,7 +411,7 @@
};
}
- @NonNull ClientMonitor.LazyDaemon<ISession> getLazySession() {
+ @NonNull HalClientMonitor.LazyDaemon<ISession> getLazySession() {
return mLazySession;
}
@@ -481,7 +492,7 @@
public void binderDied() {
Slog.e(mTag, "Binder died");
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (client instanceof Interruptable) {
Slog.e(mTag, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
final Interruptable interruptable = (Interruptable) client;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
index fbc26c6..50483d9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/TestSession.java
@@ -24,12 +24,13 @@
import android.hardware.keymaster.HardwareAuthToken;
import android.os.Binder;
import android.os.IBinder;
+import android.util.Slog;
/**
* Test session that provides mostly no-ops.
*/
public class TestSession extends ISession.Stub {
- private static final String TAG = "TestSession";
+ private static final String TAG = "FaceTestSession";
@NonNull
private final Sensor.HalSessionCallback mHalSessionCallback;
@@ -86,12 +87,16 @@
@Override
public void getAuthenticatorId(int cookie) {
+ Slog.d(TAG, "getAuthenticatorId");
+ // Immediately return a value so the framework can continue with subsequent requests.
mHalSessionCallback.onAuthenticatorIdRetrieved(0);
}
@Override
public void invalidateAuthenticatorId(int cookie) {
-
+ Slog.d(TAG, "invalidateAuthenticatorId");
+ // Immediately return a value so the framework can continue with subsequent requests.
+ mHalSessionCallback.onAuthenticatorIdInvalidated(0);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 10b12cb..5e7ddeb 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -58,10 +58,11 @@
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.EnumerateConsumer;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.Interruptable;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
@@ -103,7 +104,7 @@
@NonNull private final Context mContext;
@NonNull private final BiometricScheduler mScheduler;
@NonNull private final Handler mHandler;
- @NonNull private final ClientMonitor.LazyDaemon<IBiometricsFace> mLazyDaemon;
+ @NonNull private final HalClientMonitor.LazyDaemon<IBiometricsFace> mLazyDaemon;
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
@NonNull private final LockoutHalImpl mLockoutTracker;
@NonNull private final UsageStats mUsageStats;
@@ -170,7 +171,7 @@
.getUniqueName(mContext, userId);
final Face face = new Face(name, faceId, deviceId);
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FaceEnrollClient)) {
Slog.e(TAG, "onEnrollResult for non-enroll client: "
+ Utils.getClientName(client));
@@ -186,7 +187,7 @@
public void onAuthenticated(long deviceId, int faceId, int userId,
ArrayList<Byte> token) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(TAG, "onAuthenticated for non-authentication consumer: "
+ Utils.getClientName(client));
@@ -205,7 +206,7 @@
public void onAcquired(long deviceId, int userId, int acquiredInfo,
int vendorCode) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AcquisitionClient)) {
Slog.e(TAG, "onAcquired for non-acquire client: "
+ Utils.getClientName(client));
@@ -221,7 +222,7 @@
@Override
public void onError(long deviceId, int userId, int error, int vendorCode) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
Slog.d(TAG, "handleError"
+ ", client: " + (client != null ? client.getOwnerString() : null)
+ ", error: " + error
@@ -247,7 +248,7 @@
@Override
public void onRemoved(long deviceId, ArrayList<Integer> removed, int userId) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof RemovalConsumer)) {
Slog.e(TAG, "onRemoved for non-removal consumer: "
+ Utils.getClientName(client));
@@ -278,7 +279,7 @@
@Override
public void onEnumerate(long deviceId, ArrayList<Integer> faceIds, int userId) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof EnumerateConsumer)) {
Slog.e(TAG, "onEnumerate for non-enumerate consumer: "
+ Utils.getClientName(client));
@@ -376,7 +377,7 @@
mDaemon = null;
mCurrentUserId = UserHandle.USER_NULL;
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (client instanceof Interruptable) {
Slog.e(TAG, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
final Interruptable interruptable = (Interruptable) client;
@@ -482,7 +483,7 @@
@Override
public long getAuthenticatorId(int sensorId, int userId) {
- return mAuthenticatorIds.get(userId);
+ return mAuthenticatorIds.getOrDefault(userId, 0L);
}
@Override
@@ -528,9 +529,9 @@
final FaceGenerateChallengeClient client = new FaceGenerateChallengeClient(mContext,
mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), opPackageName,
mSensorId, mCurrentChallengeOwner);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
- public void onClientStarted(@NonNull ClientMonitor<?> clientMonitor) {
+ public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
if (client != clientMonitor) {
Slog.e(TAG, "scheduleGenerateChallenge onClientStarted, mismatched client."
+ " Expecting: " + client + ", received: " + clientMonitor);
@@ -557,9 +558,9 @@
final FaceRevokeChallengeClient client = new FaceRevokeChallengeClient(mContext,
mLazyDaemon, token, opPackageName, mSensorId);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor,
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
if (client != clientMonitor) {
Slog.e(TAG, "scheduleRevokeChallenge, mismatched client."
@@ -613,9 +614,9 @@
opPackageName, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures,
ENROLL_TIMEOUT_SEC, surfaceHandle, mSensorId);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor,
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
if (success) {
// Update authenticatorIds
@@ -724,10 +725,10 @@
final int faceId = faces.get(0).getBiometricId();
final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon,
token, listener, userId, opPackageName, mSensorId, feature, faceId);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
public void onClientFinished(
- @NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ @NonNull BaseClientMonitor clientMonitor, boolean success) {
if (success && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) {
final int settingsValue = client.getValue() ? 1 : 0;
Slog.d(TAG, "Updating attention value for user: " + userId
@@ -862,9 +863,10 @@
final FaceUpdateActiveUserClient client = new FaceUpdateActiveUserClient(mContext,
mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId, mCurrentUserId,
hasEnrolled, mAuthenticatorIds);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+ boolean success) {
if (success) {
mCurrentUserId = targetUserId;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java
index e25bb81..442303b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java
@@ -27,14 +27,14 @@
import android.os.RemoteException;
import android.util.Slog;
-import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.HalClientMonitor;
/**
* Face-specific getFeature client supporting the {@link android.hardware.biometrics.face.V1_0}
* and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
*/
-public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> {
+public class FaceGetFeatureClient extends HalClientMonitor<IBiometricsFace> {
private static final String TAG = "FaceGetFeatureClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java
index 8df9b9f..e0548e0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java
@@ -23,7 +23,7 @@
import android.os.RemoteException;
import android.util.Slog;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import java.util.ArrayList;
@@ -31,7 +31,7 @@
* Face-specific resetLockout client supporting the {@link android.hardware.biometrics.face.V1_0}
* and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
*/
-public class FaceResetLockoutClient extends ClientMonitor<IBiometricsFace> {
+public class FaceResetLockoutClient extends HalClientMonitor<IBiometricsFace> {
private static final String TAG = "FaceResetLockoutClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java
index 0e20728..4356043 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java
@@ -25,8 +25,8 @@
import android.os.RemoteException;
import android.util.Slog;
-import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import java.util.ArrayList;
@@ -34,7 +34,7 @@
* Face-specific setFeature client supporting the {@link android.hardware.biometrics.face.V1_0}
* and {@link android.hardware.biometrics.face.V1_1} HIDL interfaces.
*/
-public class FaceSetFeatureClient extends ClientMonitor<IBiometricsFace> {
+public class FaceSetFeatureClient extends HalClientMonitor<IBiometricsFace> {
private static final String TAG = "FaceSetFeatureClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java
index 22275e5..0e72f94 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java
@@ -24,12 +24,12 @@
import android.os.RemoteException;
import android.util.Slog;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import java.io.File;
import java.util.Map;
-public class FaceUpdateActiveUserClient extends ClientMonitor<IBiometricsFace> {
+public class FaceUpdateActiveUserClient extends HalClientMonitor<IBiometricsFace> {
private static final String TAG = "FaceUpdateActiveUserClient";
private static final String FACE_DATA_DIR = "facedata";
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
index 0bf107a..0aa112f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/Udfps.java
@@ -16,9 +16,11 @@
package com.android.server.biometrics.sensors.fingerprint;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
+
/**
* Interface for under-display fingerprint sensors.
- * {@link com.android.server.biometrics.sensors.ClientMonitor} subclass that require knowledge of
+ * {@link BaseClientMonitor} subclass that require knowledge of
* finger position (e.g. enroll, authenticate) should implement this.
*/
public interface Udfps {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
index a2b871e..01a620f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/UdfpsHelper.java
@@ -62,13 +62,13 @@
}
}
- public static void showUdfpsOverlay(int sensorId,
+ public static void showUdfpsOverlay(int sensorId, int reason,
@Nullable IUdfpsOverlayController udfpsOverlayController) {
if (udfpsOverlayController == null) {
return;
}
try {
- udfpsOverlayController.showUdfpsOverlay(sensorId);
+ udfpsOverlayController.showUdfpsOverlay(sensorId, reason);
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when showing the UDFPS overlay", e);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index ce0c439..82dc161 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -80,7 +80,8 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+ mUdfpsOverlayController);
try {
mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index 3398323..3b376fe 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -69,7 +69,8 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+ mUdfpsOverlayController);
try {
mCancellationSignal = getFreshDaemon().detectInteraction(mSequentialId);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index ab59abd..cacc366 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -94,7 +94,8 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_ENROLL,
+ mUdfpsOverlayController);
try {
mCancellationSignal = getFreshDaemon().enroll(mSequentialId,
HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken));
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java
index 2ad1fa3..02d4ac3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java
@@ -23,11 +23,11 @@
import android.os.RemoteException;
import android.util.Slog;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import java.util.Map;
-class FingerprintGetAuthenticatorIdClient extends ClientMonitor<ISession> {
+class FingerprintGetAuthenticatorIdClient extends HalClientMonitor<ISession> {
private static final String TAG = "FingerprintGetAuthenticatorIdClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java
index 3d07334..80d1a0f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java
@@ -18,13 +18,13 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.fingerprint.ISession;
import android.hardware.fingerprint.Fingerprint;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.sensors.InvalidationClient;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import java.util.Map;
@@ -33,8 +33,8 @@
public FingerprintInvalidationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, int userId, int sensorId,
- @NonNull FingerprintUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
- super(context, lazyDaemon, userId, sensorId, utils, authenticatorIds);
+ @NonNull Map<Integer, Long> authenticatorIds, @NonNull IInvalidationCallback callback) {
+ super(context, lazyDaemon, userId, sensorId, authenticatorIds, callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index a03deba..8a666f9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -23,6 +23,7 @@
import android.app.TaskStackListener;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.biometrics.fingerprint.SensorProps;
@@ -43,8 +44,10 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AuthenticationClient;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.HalClientMonitor;
+import com.android.server.biometrics.sensors.InvalidationRequesterClient;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.PerformanceTracker;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
@@ -73,7 +76,7 @@
@NonNull private final String mHalInstanceName;
@NonNull @VisibleForTesting
final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
- @NonNull private final ClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon;
+ @NonNull private final HalClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon;
@NonNull private final Handler mHandler;
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
@NonNull private final ActivityTaskManager mActivityTaskManager;
@@ -87,7 +90,7 @@
public void onTaskStackChanged() {
mHandler.post(() -> {
for (int i = 0; i < mSensors.size(); i++) {
- final ClientMonitor<?> client = mSensors.valueAt(i).getScheduler()
+ final BaseClientMonitor client = mSensors.valueAt(i).getScheduler()
.getCurrentClient();
if (!(client instanceof AuthenticationClient)) {
Slog.e(getTag(), "Task stack changed for client: " + client);
@@ -186,7 +189,7 @@
return mDaemon;
}
- private void scheduleForSensor(int sensorId, @NonNull ClientMonitor<?> client) {
+ private void scheduleForSensor(int sensorId, @NonNull BaseClientMonitor client) {
if (!mSensors.contains(sensorId)) {
throw new IllegalStateException("Unable to schedule client: " + client
+ " for sensor: " + sensorId);
@@ -194,8 +197,8 @@
mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
}
- private void scheduleForSensor(int sensorId, @NonNull ClientMonitor<?> client,
- ClientMonitor.Callback callback) {
+ private void scheduleForSensor(int sensorId, @NonNull BaseClientMonitor client,
+ BaseClientMonitor.Callback callback) {
if (!mSensors.contains(sensorId)) {
throw new IllegalStateException("Unable to schedule client: " + client
+ " for sensor: " + sensorId);
@@ -210,6 +213,12 @@
// this method "withoutHandler" means it should only ever be invoked from the worker thread,
// so callers will never be blocked.
mSensors.get(sensorId).createNewSession(daemon, sensorId, userId);
+
+ if (FingerprintUtils.getInstance(sensorId).isInvalidationInProgress(mContext, userId)) {
+ Slog.w(getTag(), "Scheduling unfinished invalidation request for sensor: " + sensorId
+ + ", user: " + userId);
+ scheduleInvalidationRequest(sensorId, userId);
+ }
}
@Override
@@ -266,6 +275,15 @@
});
}
+ private void scheduleInvalidationRequest(int sensorId, int userId) {
+ mHandler.post(() -> {
+ final InvalidationRequesterClient<Fingerprint> client =
+ new InvalidationRequesterClient<>(mContext, userId, sensorId,
+ FingerprintUtils.getInstance(sensorId));
+ mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+ });
+ }
+
@Override
public void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken) {
mHandler.post(() -> {
@@ -370,12 +388,13 @@
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
mUdfpsOverlayController, maxTemplatesPerUser, shouldLogMetrics);
- scheduleForSensor(sensorId, client, new ClientMonitor.Callback() {
+ scheduleForSensor(sensorId, client, new BaseClientMonitor.Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor,
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
if (success) {
scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
+ scheduleInvalidationRequest(sensorId, userId);
}
}
});
@@ -542,6 +561,33 @@
}
@Override
+ public void scheduleInvalidateAuthenticatorId(int sensorId, int userId,
+ @NonNull IInvalidationCallback callback) {
+ mHandler.post(() -> {
+ final IFingerprint daemon = getHalInstance();
+ if (daemon == null) {
+ Slog.e(getTag(), "Null daemon during scheduleInvalidateAuthenticatorId: "
+ + sensorId);
+ return;
+ }
+
+ try {
+ if (!mSensors.get(sensorId).hasSessionForUser(userId)) {
+ createNewSessionWithoutHandler(daemon, sensorId, userId);
+ }
+
+ final FingerprintInvalidationClient client =
+ new FingerprintInvalidationClient(mContext,
+ mSensors.get(sensorId).getLazySession(), userId, sensorId,
+ mSensors.get(sensorId).getAuthenticatorIds(), callback);
+ mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client);
+ } catch (RemoteException e) {
+ Slog.e(getTag(), "Remote exception", e);
+ }
+ });
+ }
+
+ @Override
public int getLockoutModeForUser(int sensorId, int userId) {
return mSensors.get(sensorId).getLockoutCache().getLockoutModeForUser(userId);
}
@@ -553,7 +599,8 @@
@Override
public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
- final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient();
+ final BaseClientMonitor client =
+ mSensors.get(sensorId).getScheduler().getCurrentClient();
if (!(client instanceof Udfps)) {
Slog.e(getTag(), "onPointerDown received during client: " + client);
return;
@@ -564,7 +611,8 @@
@Override
public void onPointerUp(int sensorId) {
- final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient();
+ final BaseClientMonitor client =
+ mSensors.get(sensorId).getScheduler().getCurrentClient();
if (!(client instanceof Udfps)) {
Slog.e(getTag(), "onPointerUp received during client: " + client);
return;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java
index 1f1d19d..cd84cdf 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java
@@ -26,7 +26,7 @@
import android.util.Slog;
import com.android.server.biometrics.HardwareAuthTokenUtils;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
@@ -36,7 +36,7 @@
* Updates the framework's lockout cache and notifies clients such as Keyguard when lockout is
* cleared.
*/
-class FingerprintResetLockoutClient extends ClientMonitor<ISession> {
+class FingerprintResetLockoutClient extends HalClientMonitor<ISession> {
private static final String TAG = "FingerprintResetLockoutClient";
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index bb0f983..911f6b4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -45,9 +45,10 @@
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.EnumerateConsumer;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.Interruptable;
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutConsumer;
@@ -78,7 +79,7 @@
@NonNull private final Map<Integer, Long> mAuthenticatorIds;
@Nullable private Session mCurrentSession;
- @NonNull private final ClientMonitor.LazyDaemon<ISession> mLazySession;
+ @NonNull private final HalClientMonitor.LazyDaemon<ISession> mLazySession;
static class Session {
@NonNull private final String mTag;
@@ -136,7 +137,7 @@
@Override
public void onChallengeGenerated(long challenge) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FingerprintGenerateChallengeClient)) {
Slog.e(mTag, "onChallengeGenerated for wrong client: "
+ Utils.getClientName(client));
@@ -152,7 +153,7 @@
@Override
public void onChallengeRevoked(long challenge) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FingerprintRevokeChallengeClient)) {
Slog.e(mTag, "onChallengeRevoked for wrong client: "
+ Utils.getClientName(client));
@@ -168,7 +169,7 @@
@Override
public void onAcquired(byte info, int vendorCode) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AcquisitionClient)) {
Slog.e(mTag, "onAcquired for non-acquisition client: "
+ Utils.getClientName(client));
@@ -183,7 +184,7 @@
@Override
public void onError(byte error, int vendorCode) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
Slog.d(mTag, "onError"
+ ", client: " + Utils.getClientName(client)
+ ", error: " + error
@@ -206,7 +207,7 @@
@Override
public void onEnrollmentProgress(int enrollmentId, int remaining) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FingerprintEnrollClient)) {
Slog.e(mTag, "onEnrollmentProgress for non-enroll client: "
+ Utils.getClientName(client));
@@ -226,7 +227,7 @@
@Override
public void onAuthenticationSucceeded(int enrollmentId, HardwareAuthToken hat) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(mTag, "onAuthenticationSucceeded for non-authentication consumer: "
+ Utils.getClientName(client));
@@ -249,7 +250,7 @@
@Override
public void onAuthenticationFailed() {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(mTag, "onAuthenticationFailed for non-authentication consumer: "
+ Utils.getClientName(client));
@@ -267,7 +268,7 @@
@Override
public void onLockoutTimed(long durationMillis) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof LockoutConsumer)) {
Slog.e(mTag, "onLockoutTimed for non-lockout consumer: "
+ Utils.getClientName(client));
@@ -282,7 +283,7 @@
@Override
public void onLockoutPermanent() {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof LockoutConsumer)) {
Slog.e(mTag, "onLockoutPermanent for non-lockout consumer: "
+ Utils.getClientName(client));
@@ -297,7 +298,7 @@
@Override
public void onLockoutCleared() {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FingerprintResetLockoutClient)) {
Slog.e(mTag, "onLockoutCleared for non-resetLockout client: "
+ Utils.getClientName(client));
@@ -313,7 +314,7 @@
@Override
public void onInteractionDetected() {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FingerprintDetectClient)) {
Slog.e(mTag, "onInteractionDetected for non-detect client: "
+ Utils.getClientName(client));
@@ -329,7 +330,7 @@
@Override
public void onEnrollmentsEnumerated(int[] enrollmentIds) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof EnumerateConsumer)) {
Slog.e(mTag, "onEnrollmentsEnumerated for non-enumerate consumer: "
+ Utils.getClientName(client));
@@ -352,7 +353,7 @@
@Override
public void onEnrollmentsRemoved(int[] enrollmentIds) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof RemovalConsumer)) {
Slog.e(mTag, "onRemoved for non-removal consumer: "
+ Utils.getClientName(client));
@@ -374,7 +375,7 @@
@Override
public void onAuthenticatorIdRetrieved(long authenticatorId) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FingerprintGetAuthenticatorIdClient)) {
Slog.e(mTag, "onAuthenticatorIdRetrieved for wrong consumer: "
+ Utils.getClientName(client));
@@ -389,7 +390,18 @@
@Override
public void onAuthenticatorIdInvalidated(long newAuthenticatorId) {
- // TODO(159667191)
+ mHandler.post(() -> {
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
+ if (!(client instanceof FingerprintInvalidationClient)) {
+ Slog.e(mTag, "onAuthenticatorIdInvalidated for wrong consumer: "
+ + Utils.getClientName(client));
+ return;
+ }
+
+ final FingerprintInvalidationClient invalidationClient =
+ (FingerprintInvalidationClient) client;
+ invalidationClient.onAuthenticatorIdInvalidated(newAuthenticatorId);
+ });
}
}
@@ -413,7 +425,7 @@
};
}
- @NonNull ClientMonitor.LazyDaemon<ISession> getLazySession() {
+ @NonNull HalClientMonitor.LazyDaemon<ISession> getLazySession() {
return mLazySession;
}
@@ -494,7 +506,7 @@
public void binderDied() {
Slog.e(mTag, "Binder died");
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (client instanceof Interruptable) {
Slog.e(mTag, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
final Interruptable interruptable = (Interruptable) client;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java
index ddae110..ac4f665 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestSession.java
@@ -30,7 +30,7 @@
*/
class TestSession extends ISession.Stub {
- private static final String TAG = "TestSession";
+ private static final String TAG = "FingerprintTestSession";
@NonNull private final Sensor.HalSessionCallback mHalSessionCallback;
@@ -92,7 +92,9 @@
@Override
public void invalidateAuthenticatorId(int cookie) {
-
+ Slog.d(TAG, "invalidateAuthenticatorId");
+ // Immediately return a value so the framework can continue with subsequent requests.
+ mHalSessionCallback.onAuthenticatorIdInvalidated(0);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 7989e6e4..6cc8687 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -58,10 +58,11 @@
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.EnumerateConsumer;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.Interruptable;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
@@ -103,7 +104,7 @@
private final LockoutResetDispatcher mLockoutResetDispatcher;
private final LockoutFrameworkImpl mLockoutTracker;
private final BiometricTaskStackListener mTaskStackListener;
- private final ClientMonitor.LazyDaemon<IBiometricsFingerprint> mLazyDaemon;
+ private final HalClientMonitor.LazyDaemon<IBiometricsFingerprint> mLazyDaemon;
private final Map<Integer, Long> mAuthenticatorIds;
@Nullable private IBiometricsFingerprint mDaemon;
@@ -116,7 +117,7 @@
@Override
public void onTaskStackChanged() {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationClient)) {
Slog.e(TAG, "Task stack changed for client: " + client);
return;
@@ -188,7 +189,7 @@
@Override
public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof FingerprintEnrollClient)) {
Slog.e(TAG, "onEnrollResult for non-enroll client: "
+ Utils.getClientName(client));
@@ -213,7 +214,7 @@
@Override
public void onAcquired_2_2(long deviceId, int acquiredInfo, int vendorCode) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AcquisitionClient)) {
Slog.e(TAG, "onAcquired for non-acquisition client: "
+ Utils.getClientName(client));
@@ -229,7 +230,7 @@
public void onAuthenticated(long deviceId, int fingerId, int groupId,
ArrayList<Byte> token) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(TAG, "onAuthenticated for non-authentication consumer: "
+ Utils.getClientName(client));
@@ -247,7 +248,7 @@
@Override
public void onError(long deviceId, int error, int vendorCode) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
Slog.d(TAG, "handleError"
+ ", client: " + Utils.getClientName(client)
+ ", error: " + error
@@ -273,7 +274,7 @@
public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.post(() -> {
Slog.d(TAG, "Removed, fingerId: " + fingerId + ", remaining: " + remaining);
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof RemovalConsumer)) {
Slog.e(TAG, "onRemoved for non-removal consumer: "
+ Utils.getClientName(client));
@@ -289,7 +290,7 @@
@Override
public void onEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof EnumerateConsumer)) {
Slog.e(TAG, "onEnumerate for non-enumerate consumer: "
+ Utils.getClientName(client));
@@ -379,7 +380,7 @@
mDaemon = null;
mCurrentUserId = UserHandle.USER_NULL;
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (client instanceof Interruptable) {
Slog.e(TAG, "Sending ERROR_HW_UNAVAILABLE for client: " + client);
final Interruptable interruptable = (Interruptable) client;
@@ -484,9 +485,10 @@
new FingerprintUpdateActiveUserClient(mContext, mLazyDaemon, targetUserId,
mContext.getOpPackageName(), mSensorProperties.sensorId, mCurrentUserId,
hasEnrolled, mAuthenticatorIds);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+ boolean success) {
if (success) {
mCurrentUserId = targetUserId;
}
@@ -557,9 +559,9 @@
hardwareAuthToken, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId),
ENROLL_TIMEOUT_SEC, mSensorProperties.sensorId, mUdfpsOverlayController,
shouldLogMetrics);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor,
+ public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
if (success) {
// Update authenticatorIds
@@ -681,12 +683,12 @@
@Override
public long getAuthenticatorId(int sensorId, int userId) {
- return mAuthenticatorIds.get(userId);
+ return mAuthenticatorIds.getOrDefault(userId, 0L);
}
@Override
public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof Udfps)) {
Slog.w(TAG, "onFingerDown received during client: " + client);
return;
@@ -697,7 +699,7 @@
@Override
public void onPointerUp(int sensorId) {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof Udfps)) {
Slog.w(TAG, "onFingerDown received during client: " + client);
return;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index 791d224..2394a70 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -40,8 +40,8 @@
import com.android.internal.R;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.ClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
@@ -146,14 +146,14 @@
class TestableInternalCallback extends InternalCallback {
@Override
- public void onClientStarted(ClientMonitor<?> clientMonitor) {
+ public void onClientStarted(BaseClientMonitor clientMonitor) {
super.onClientStarted(clientMonitor);
Slog.d(TAG, "Client started: " + clientMonitor);
mFingerprint21.setDebugMessage("Started: " + clientMonitor);
}
@Override
- public void onClientFinished(ClientMonitor<?> clientMonitor, boolean success) {
+ public void onClientFinished(BaseClientMonitor clientMonitor, boolean success) {
super.onClientFinished(clientMonitor, success);
Slog.d(TAG, "Client finished: " + clientMonitor);
mFingerprint21.setDebugMessage("Finished: " + clientMonitor);
@@ -175,7 +175,7 @@
/**
* All of the mocking/testing should happen in here. This way we don't need to modify the
- * {@link com.android.server.biometrics.sensors.ClientMonitor} implementations and can run the
+ * {@link BaseClientMonitor} implementations and can run the
* real path there.
*/
private static class MockHalResultController extends HalResultController {
@@ -233,7 +233,7 @@
public void onAuthenticated(long deviceId, int fingerId, int groupId,
ArrayList<Byte> token) {
mHandler.post(() -> {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
if (!(client instanceof AuthenticationConsumer)) {
Slog.e(TAG, "Non authentication consumer: " + client);
return;
@@ -360,7 +360,7 @@
@Override
public void run() {
- final ClientMonitor<?> client = mScheduler.getCurrentClient();
+ final BaseClientMonitor client = mScheduler.getCurrentClient();
// We don't care about FingerprintDetectClient, since accept/rejects are both OK. UDFPS
// rejects will just simulate the path where non-enrolled fingers are presented.
@@ -466,7 +466,7 @@
Slog.d(TAG, "onFingerDown");
final AuthenticationConsumer lastAuthenticatedConsumer =
mMockHalResultController.getLastAuthenticatedClient();
- final ClientMonitor<?> currentScheduledClient = mScheduler.getCurrentClient();
+ final BaseClientMonitor currentScheduledClient = mScheduler.getCurrentClient();
if (currentScheduledClient == null) {
Slog.d(TAG, "Not authenticating");
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 46605d1..784e37b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -113,7 +113,8 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+ mUdfpsOverlayController);
try {
// GroupId was never used. In fact, groupId is always the same as userId.
getFreshDaemon().authenticate(mOperationId, getTargetUserId());
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index 4747488..55995ea 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -82,7 +82,8 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
+ mUdfpsOverlayController);
try {
getFreshDaemon().authenticate(0 /* operationId */, getTargetUserId());
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index d1f1cf8..b2e3c33 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -76,7 +76,8 @@
@Override
protected void startHalOperation() {
- UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
+ UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_ENROLL,
+ mUdfpsOverlayController);
try {
// GroupId was never used. In fact, groupId is always the same as userId.
getFreshDaemon().enroll(mHardwareAuthToken, getTargetUserId(), mTimeoutSec);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java
index 00e2413..f6ec4d9 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java
@@ -26,7 +26,7 @@
import android.os.SELinux;
import android.util.Slog;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import java.io.File;
import java.util.Map;
@@ -34,7 +34,7 @@
/**
* Sets the HAL's current active user, and updates the framework's authenticatorId cache.
*/
-public class FingerprintUpdateActiveUserClient extends ClientMonitor<IBiometricsFingerprint> {
+public class FingerprintUpdateActiveUserClient extends HalClientMonitor<IBiometricsFingerprint> {
private static final String TAG = "FingerprintUpdateActiveUserClient";
private static final String FP_DATA_DIR = "fpdata";
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 2a81426..40d2073 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -57,6 +57,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -466,8 +467,13 @@
streamProtos[i].firstCaptureLatencyMillis = streamStats.getStartLatencyMs();
streamProtos[i].maxHalBuffers = streamStats.getMaxHalBuffers();
streamProtos[i].maxAppBuffers = streamStats.getMaxAppBuffers();
+ streamProtos[i].histogramType = streamStats.getHistogramType();
+ streamProtos[i].histogramBins = streamStats.getHistogramBins();
+ streamProtos[i].histogramCounts = streamStats.getHistogramCounts();
if (CameraServiceProxy.DEBUG) {
+ String histogramTypeName =
+ cameraHistogramTypeToString(streamProtos[i].histogramType);
Slog.v(TAG, "Stream " + i + ": width " + streamProtos[i].width
+ ", height " + streamProtos[i].height
+ ", format " + streamProtos[i].format
@@ -478,7 +484,12 @@
+ ", firstCaptureLatencyMillis "
+ streamProtos[i].firstCaptureLatencyMillis
+ ", maxHalBuffers " + streamProtos[i].maxHalBuffers
- + ", maxAppBuffers " + streamProtos[i].maxAppBuffers);
+ + ", maxAppBuffers " + streamProtos[i].maxAppBuffers
+ + ", histogramType " + histogramTypeName
+ + ", histogramBins "
+ + Arrays.toString(streamProtos[i].histogramBins)
+ + ", histogramCounts "
+ + Arrays.toString(streamProtos[i].histogramCounts));
}
}
}
@@ -797,4 +808,14 @@
return "CAMERA_FACING_UNKNOWN";
}
+ private static String cameraHistogramTypeToString(int cameraHistogramType) {
+ switch (cameraHistogramType) {
+ case CameraStreamStats.HISTOGRAM_TYPE_CAPTURE_LATENCY:
+ return "HISTOGRAM_TYPE_CAPTURE_LATENCY";
+ default:
+ break;
+ }
+ return "HISTOGRAM_TYPE_UNKNOWN";
+ }
+
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index b0a73f1..8215e88 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -136,12 +136,12 @@
// This Network object should always be used if possible, so as to encourage reuse of the
// enclosed socket factory and connection pool. Avoid creating other Network objects.
// This Network object is always valid.
- public final Network network;
- public LinkProperties linkProperties;
+ @NonNull public final Network network;
+ @NonNull public LinkProperties linkProperties;
// This should only be modified by ConnectivityService, via setNetworkCapabilities().
// TODO: make this private with a getter.
- public NetworkCapabilities networkCapabilities;
- public final NetworkAgentConfig networkAgentConfig;
+ @NonNull public NetworkCapabilities networkCapabilities;
+ @NonNull public final NetworkAgentConfig networkAgentConfig;
// Underlying networks declared by the agent. Only set if supportsUnderlyingNetworks is true.
// The networks in this list might be declared by a VPN app using setUnderlyingNetworks and are
@@ -603,7 +603,7 @@
*
* @return the old capabilities of this network.
*/
- public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
+ @NonNull public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
@NonNull final NetworkCapabilities nc) {
final NetworkCapabilities oldNc = networkCapabilities;
networkCapabilities = nc;
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacProxyInstaller.java
similarity index 82%
rename from services/core/java/com/android/server/connectivity/PacManager.java
rename to services/core/java/com/android/server/connectivity/PacProxyInstaller.java
index 93930ae..5dc8c1a 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacProxyInstaller.java
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2013, The Android Open Source Project
+/*
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.server.connectivity;
+import android.annotation.NonNull;
import android.annotation.WorkerThread;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -52,7 +54,7 @@
/**
* @hide
*/
-public class PacManager {
+public class PacProxyInstaller {
private static final String PAC_PACKAGE = "com.android.pacprocessor";
private static final String PAC_SERVICE = "com.android.pacprocessor.PacService";
private static final String PAC_SERVICE_NAME = "com.android.net.IProxyService";
@@ -60,7 +62,7 @@
private static final String PROXY_PACKAGE = "com.android.proxyhandler";
private static final String PROXY_SERVICE = "com.android.proxyhandler.ProxyService";
- private static final String TAG = "PacManager";
+ private static final String TAG = "PacProxyInstaller";
private static final String ACTION_PAC_REFRESH = "android.net.proxy.PAC_REFRESH";
@@ -70,10 +72,6 @@
private static final int DELAY_LONG = 4;
private static final long MAX_PAC_SIZE = 20 * 1000 * 1000;
- // Return values for #setCurrentProxyScriptUrl
- public static final boolean DONT_SEND_BROADCAST = false;
- public static final boolean DO_SEND_BROADCAST = true;
-
private String mCurrentPac;
@GuardedBy("mProxyLock")
private volatile Uri mPacUrl = Uri.EMPTY;
@@ -92,7 +90,7 @@
private volatile boolean mHasSentBroadcast;
private volatile boolean mHasDownloaded;
- private Handler mConnectivityHandler;
+ private final Handler mConnectivityHandler;
private final int mProxyMessage;
/**
@@ -101,6 +99,13 @@
private final Object mProxyLock = new Object();
/**
+ * Lock ensuring consistency between the values of mHasSentBroadcast, mHasDownloaded, the
+ * last URL and port, and the broadcast message being sent with the correct arguments.
+ * TODO : this should probably protect all instances of these variables
+ */
+ private final Object mBroadcastStateLock = new Object();
+
+ /**
* Runnable to download PAC script.
* The behavior relies on the assumption it always runs on mNetThread to guarantee that the
* latest data fetched from mPacUrl is stored in mProxyService.
@@ -145,10 +150,10 @@
}
}
- public PacManager(Context context, Handler handler, int proxyMessage) {
+ public PacProxyInstaller(@NonNull Context context, @NonNull Handler handler, int proxyMessage) {
mContext = context;
mLastPort = -1;
- final HandlerThread netThread = new HandlerThread("android.pacmanager",
+ final HandlerThread netThread = new HandlerThread("android.pacproxyinstaller",
android.os.Process.THREAD_PRIORITY_DEFAULT);
netThread.start();
mNetThreadHandler = new Handler(netThread.getLooper());
@@ -163,43 +168,39 @@
private AlarmManager getAlarmManager() {
if (mAlarmManager == null) {
- mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
+ mAlarmManager = mContext.getSystemService(AlarmManager.class);
}
return mAlarmManager;
}
/**
- * Updates the PAC Manager with current Proxy information. This is called by
+ * Updates the PAC Proxy Installer with current Proxy information. This is called by
* the ProxyTracker directly before a broadcast takes place to allow
- * the PacManager to indicate that the broadcast should not be sent and the
- * PacManager will trigger a new broadcast when it is ready.
+ * the PacProxyInstaller to indicate that the broadcast should not be sent and the
+ * PacProxyInstaller will trigger a new broadcast when it is ready.
*
* @param proxy Proxy information that is about to be broadcast.
- * @return Returns whether the broadcast should be sent : either DO_ or DONT_SEND_BROADCAST
*/
- public synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) {
- if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
- if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) {
- // Allow to send broadcast, nothing to do.
- return DO_SEND_BROADCAST;
- }
- mPacUrl = proxy.getPacFileUrl();
- mCurrentDelay = DELAY_1;
- mHasSentBroadcast = false;
- mHasDownloaded = false;
- getAlarmManager().cancel(mPacRefreshIntent);
- bind();
- return DONT_SEND_BROADCAST;
- } else {
- getAlarmManager().cancel(mPacRefreshIntent);
- synchronized (mProxyLock) {
- mPacUrl = Uri.EMPTY;
- mCurrentPac = null;
- if (mProxyService != null) {
- unbind();
+ public void setCurrentProxyScriptUrl(@NonNull ProxyInfo proxy) {
+ synchronized (mBroadcastStateLock) {
+ if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
+ if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) return;
+ mPacUrl = proxy.getPacFileUrl();
+ mCurrentDelay = DELAY_1;
+ mHasSentBroadcast = false;
+ mHasDownloaded = false;
+ getAlarmManager().cancel(mPacRefreshIntent);
+ bind();
+ } else {
+ getAlarmManager().cancel(mPacRefreshIntent);
+ synchronized (mProxyLock) {
+ mPacUrl = Uri.EMPTY;
+ mCurrentPac = null;
+ if (mProxyService != null) {
+ unbind();
+ }
}
}
- return DO_SEND_BROADCAST;
}
}
@@ -233,10 +234,10 @@
}
private int getNextDelay(int currentDelay) {
- if (++currentDelay > DELAY_4) {
- return DELAY_4;
- }
- return currentDelay;
+ if (++currentDelay > DELAY_4) {
+ return DELAY_4;
+ }
+ return currentDelay;
}
private void longSchedule() {
@@ -274,6 +275,7 @@
getAlarmManager().set(AlarmManager.ELAPSED_REALTIME, timeTillTrigger, mPacRefreshIntent);
}
+ @GuardedBy("mProxyLock")
private void setCurrentProxyScript(String script) {
if (mProxyService == null) {
Log.e(TAG, "setCurrentProxyScript: no proxy service");
@@ -346,6 +348,9 @@
public void setProxyPort(int port) {
if (mLastPort != -1) {
// Always need to send if port changed
+ // TODO: Here lacks synchronization because this write cannot
+ // guarantee that it's visible from sendProxyIfNeeded() when
+ // it's called by a Runnable which is post by mNetThread.
mHasSentBroadcast = false;
}
mLastPort = port;
@@ -385,13 +390,15 @@
mConnectivityHandler.sendMessage(mConnectivityHandler.obtainMessage(mProxyMessage, proxy));
}
- private synchronized void sendProxyIfNeeded() {
- if (!mHasDownloaded || (mLastPort == -1)) {
- return;
- }
- if (!mHasSentBroadcast) {
- sendPacBroadcast(ProxyInfo.buildPacProxy(mPacUrl, mLastPort));
- mHasSentBroadcast = true;
+ private void sendProxyIfNeeded() {
+ synchronized (mBroadcastStateLock) {
+ if (!mHasDownloaded || (mLastPort == -1)) {
+ return;
+ }
+ if (!mHasSentBroadcast) {
+ sendPacBroadcast(ProxyInfo.buildPacProxy(mPacUrl, mLastPort));
+ mHasSentBroadcast = true;
+ }
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index f6ca152..b618d2b 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2018, The Android Open Source Project
+ * Copyright (c) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@
// is not set. Individual networks have their own settings that override this. This member
// is set through setDefaultProxy, which is called when the default network changes proxies
// in its LinkProperties, or when ConnectivityService switches to a new default network, or
- // when PacManager resolves the proxy.
+ // when PacProxyInstaller resolves the proxy.
@Nullable
@GuardedBy("mProxyLock")
private volatile ProxyInfo mDefaultProxy = null;
@@ -79,13 +79,14 @@
// The object responsible for Proxy Auto Configuration (PAC).
@NonNull
- private final PacManager mPacManager;
+ private final PacProxyInstaller mPacProxyInstaller;
public ProxyTracker(@NonNull final Context context,
@NonNull final Handler connectivityServiceInternalHandler, final int pacChangedEvent) {
mContext = context;
mConnectivityServiceHandler = connectivityServiceInternalHandler;
- mPacManager = new PacManager(context, connectivityServiceInternalHandler, pacChangedEvent);
+ mPacProxyInstaller = new PacProxyInstaller(
+ context, connectivityServiceInternalHandler, pacChangedEvent);
}
// Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present
@@ -181,7 +182,7 @@
if (!TextUtils.isEmpty(pacFileUrl)) {
mConnectivityServiceHandler.post(
- () -> mPacManager.setCurrentProxyScriptUrl(proxyProperties));
+ () -> mPacProxyInstaller.setCurrentProxyScriptUrl(proxyProperties));
}
}
}
@@ -225,7 +226,9 @@
final ProxyInfo defaultProxy = getDefaultProxy();
final ProxyInfo proxyInfo = null != defaultProxy ?
defaultProxy : ProxyInfo.buildDirectProxy("", 0, Collections.emptyList());
- if (mPacManager.setCurrentProxyScriptUrl(proxyInfo) == PacManager.DONT_SEND_BROADCAST) {
+ mPacProxyInstaller.setCurrentProxyScriptUrl(proxyInfo);
+
+ if (!shouldSendBroadcast(proxyInfo)) {
return;
}
if (DBG) Log.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
@@ -241,6 +244,13 @@
}
}
+ private boolean shouldSendBroadcast(ProxyInfo proxy) {
+ if (Uri.EMPTY.equals(proxy.getPacFileUrl())) return false;
+ if (proxy.getPacFileUrl().equals(proxy.getPacFileUrl())
+ && (proxy.getPort() > 0)) return true;
+ return true;
+ }
+
/**
* Sets the global proxy in memory. Also writes the values to the global settings of the device.
*
@@ -305,10 +315,10 @@
return;
}
- // This call could be coming from the PacManager, containing the port of the local
- // proxy. If this new proxy matches the global proxy then copy this proxy to the
+ // This call could be coming from the PacProxyInstaller, containing the port of the
+ // local proxy. If this new proxy matches the global proxy then copy this proxy to the
// global (to get the correct local port), and send a broadcast.
- // TODO: Switch PacManager to have its own message to send back rather than
+ // TODO: Switch PacProxyInstaller to have its own message to send back rather than
// reusing EVENT_HAS_CHANGED_PROXY and this call to handleApplyDefaultProxy.
if ((mGlobalProxy != null) && (proxyInfo != null)
&& (!Uri.EMPTY.equals(proxyInfo.getPacFileUrl()))
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index b250f16..a65f809 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1229,7 +1229,8 @@
private boolean canHaveRestrictedProfile(int userId) {
final long token = Binder.clearCallingIdentity();
try {
- return UserManager.get(mContext).canHaveRestrictedProfile(userId);
+ final Context userContext = mContext.createContextAsUser(UserHandle.of(userId), 0);
+ return userContext.getSystemService(UserManager.class).canHaveRestrictedProfile();
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 60e4595..55103ca 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -49,6 +49,7 @@
import android.graphics.ColorSpace;
import android.graphics.Point;
import android.hardware.SensorManager;
+import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
import android.hardware.display.BrightnessConfiguration;
@@ -71,6 +72,7 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IBinder.DeathRecipient;
import android.os.Looper;
@@ -100,7 +102,6 @@
import android.view.Display;
import android.view.DisplayEventReceiver;
import android.view.DisplayInfo;
-import android.view.IDisplayFoldListener;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -114,7 +115,6 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiThread;
-import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -360,8 +360,8 @@
// Receives notifications about changes to Settings.
private SettingsObserver mSettingsObserver;
- // Received notifications of the display-fold action
- private DisplayFoldListener mDisplayFoldListener;
+ // Received notifications of the device-state action (such as "fold", "unfold")
+ private DeviceStateManager mDeviceStateManager;
private final boolean mAllowNonNativeRefreshRateOverride;
@@ -504,10 +504,11 @@
synchronized (mSyncRoot) {
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
- WindowManagerPolicy policy = LocalServices.getService(WindowManagerPolicy.class);
- mDisplayFoldListener = new DisplayFoldListener();
- policy.registerDisplayFoldListener(mDisplayFoldListener);
+ DeviceStateManager deviceStateManager =
+ mContext.getSystemService(DeviceStateManager.class);
+ deviceStateManager.registerDeviceStateListener(new DeviceStateListener(),
+ new HandlerExecutor(mHandler));
scheduleTraversalLocked(false);
}
@@ -2880,15 +2881,14 @@
}
}
- class DisplayFoldListener extends IDisplayFoldListener.Stub {
+ /**
+ * Listens to changes in device state and reports the state to LogicalDisplayMapper.
+ */
+ class DeviceStateListener implements DeviceStateManager.DeviceStateListener {
@Override
- public void onDisplayFoldChanged(int displayId, boolean folded) {
- // TODO: multi-display - IDisplayFoldListener callback only really works for the
- // Display.DEFAULT_DISPLAY.
- if (displayId == Display.DEFAULT_DISPLAY) {
- synchronized (mSyncRoot) {
- mLogicalDisplayMapper.setDeviceFoldedLocked(folded);
- }
+ public void onDeviceStateChanged(int deviceState) {
+ synchronized (mSyncRoot) {
+ mLogicalDisplayMapper.setDeviceStateLocked(deviceState);
}
}
};
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index a127858..bb2fbed 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -103,6 +103,7 @@
private final DisplayDeviceRepository mDisplayDeviceRepo;
private final Listener mListener;
+ private final int mFoldedDeviceState;
LogicalDisplayMapper(Context context, DisplayDeviceRepository repo, Listener listener) {
mDisplayDeviceRepo = repo;
@@ -110,6 +111,9 @@
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mDisplayDeviceRepo.addListener(this);
+ mFoldedDeviceState = context.getResources().getInteger(
+ com.android.internal.R.integer.config_foldedDeviceState);
+
loadFoldedDisplayConfig(context);
}
@@ -211,6 +215,10 @@
}
}
+ void setDeviceStateLocked(int state) {
+ setDeviceFoldedLocked(state == mFoldedDeviceState);
+ }
+
void setDeviceFoldedLocked(boolean isFolded) {
mIsFolded = isFolded;
if (mIsFoldedOverride != null) {
diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
index 521ce69..633c0c4 100644
--- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
+++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java
@@ -20,15 +20,28 @@
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Typeface;
+import android.graphics.fonts.FontFamily;
+import android.graphics.fonts.FontFileUtil;
+import android.graphics.fonts.SystemFonts;
import android.os.SharedMemory;
import android.system.ErrnoException;
+import android.text.FontConfig;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.NioUtils;
+import java.nio.channels.FileChannel;
+import java.util.HashMap;
+import java.util.Map;
/** A service for managing system fonts. */
// TODO(b/173619554): Add API to update fonts.
@@ -36,6 +49,10 @@
private static final String TAG = "FontManagerService";
+ // TODO: make this a DeviceConfig flag.
+ private static final boolean ENABLE_FONT_UPDATES = false;
+ private static final String FONT_FILES_DIR = "/data/fonts/files";
+
/** Class to manage FontManagerService's lifecycle. */
public static final class Lifecycle extends SystemService {
private final FontManagerService mService;
@@ -58,10 +75,37 @@
}
}
- @GuardedBy("this")
+ private static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
+ @Override
+ public long getVersion(File file) throws IOException {
+ ByteBuffer buffer = mmap(file);
+ try {
+ return FontFileUtil.getRevision(buffer, 0);
+ } finally {
+ NioUtils.freeDirectBuffer(buffer);
+ }
+ }
+
+ private static ByteBuffer mmap(File file) throws IOException {
+ try (FileInputStream in = new FileInputStream(file)) {
+ FileChannel fileChannel = in.getChannel();
+ return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
+ }
+ }
+ }
+
+ @Nullable
+ private final UpdatableFontDir mUpdatableFontDir;
+
+ @GuardedBy("FontManagerService.this")
@Nullable
private SharedMemory mSerializedSystemFontMap = null;
+ private FontManagerService() {
+ mUpdatableFontDir = ENABLE_FONT_UPDATES
+ ? new UpdatableFontDir(new File(FONT_FILES_DIR), new OtfFontFileParser()) : null;
+ }
+
@Nullable
private SharedMemory getSerializedSystemFontMap() {
if (!Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {
@@ -77,7 +121,19 @@
@Nullable
private SharedMemory createSerializedSystemFontMapLocked() {
- // TODO(b/173619554): use updated fonts.
+ if (mUpdatableFontDir != null) {
+ HashMap<String, Typeface> systemFontMap = new HashMap<>();
+ Map<String, File> fontFileMap = mUpdatableFontDir.getFontFileMap();
+ Pair<FontConfig.Alias[], Map<String, FontFamily[]>> pair =
+ SystemFonts.initializeSystemFonts(fontFileMap);
+ Typeface.initSystemDefaultTypefaces(systemFontMap, pair.second, pair.first);
+ try {
+ return Typeface.serializeFontMap(systemFontMap);
+ } catch (IOException | ErrnoException e) {
+ Slog.w(TAG, "Failed to serialize updatable font map. "
+ + "Retrying with system image fonts.", e);
+ }
+ }
try {
return Typeface.serializeFontMap(Typeface.getSystemFontMap());
} catch (IOException | ErrnoException e) {
@@ -85,4 +141,19 @@
}
return null;
}
+
+ private boolean installFontFile(String name, FileDescriptor fd) {
+ if (mUpdatableFontDir == null) return false;
+ synchronized (FontManagerService.this) {
+ try {
+ mUpdatableFontDir.installFontFile(name, fd);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to install font file: " + name, e);
+ return false;
+ }
+ // Create updated font map in the next getSerializedSystemFontMap() call.
+ mSerializedSystemFontMap = null;
+ return true;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
new file mode 100644
index 0000000..7306471
--- /dev/null
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.graphics.fonts;
+
+import android.os.FileUtils;
+import android.util.Base64;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.SecureRandom;
+import java.util.HashMap;
+import java.util.Map;
+
+final class UpdatableFontDir {
+
+ private static final String TAG = "UpdatableFontDir";
+ private static final String RANDOM_DIR_PREFIX = "~~";
+
+ /** Interface to mock font file access in tests. */
+ interface FontFileParser {
+ long getVersion(File file) throws IOException;
+ }
+
+ /** Data class to hold font file path and version. */
+ static final class FontFileInfo {
+ final File mFile;
+ final long mVersion;
+
+ FontFileInfo(File file, long version) {
+ mFile = file;
+ mVersion = version;
+ }
+ }
+
+ /**
+ * Root directory for storing updated font files. Each font file is stored in a unique random
+ * dir. The font file path would be {@code mFilesDir/~~{randomStr}/{fontFileName}}.
+ */
+ private final File mFilesDir;
+ private final FontFileParser mParser;
+ @GuardedBy("UpdatableFontDir.this")
+ private final Map<String, FontFileInfo> mFontFileInfoMap = new HashMap<>();
+
+ UpdatableFontDir(File filesDir, FontFileParser parser) {
+ mFilesDir = filesDir;
+ mParser = parser;
+ loadFontFileMap();
+ }
+
+ private void loadFontFileMap() {
+ synchronized (UpdatableFontDir.this) {
+ mFontFileInfoMap.clear();
+ File[] dirs = mFilesDir.listFiles();
+ if (dirs == null) return;
+ for (File dir : dirs) {
+ if (!dir.getName().startsWith(RANDOM_DIR_PREFIX)) continue;
+ File[] files = dir.listFiles();
+ if (files == null || files.length != 1) continue;
+ addFileToMapLocked(files[0], true);
+ }
+ }
+ }
+
+ void installFontFile(String name, FileDescriptor fd) throws IOException {
+ // TODO: Validate name.
+ synchronized (UpdatableFontDir.this) {
+ // TODO: proper error handling
+ File newDir = getRandomDir(mFilesDir);
+ if (!newDir.mkdir()) {
+ throw new IOException("Failed to create a new dir");
+ }
+ File newFontFile = new File(newDir, name);
+ try (FileOutputStream out = new FileOutputStream(newFontFile)) {
+ FileUtils.copy(fd, out.getFD());
+ }
+ addFileToMapLocked(newFontFile, false);
+ }
+ }
+
+ /**
+ * Given {@code parent}, returns {@code parent/~~[randomStr]}.
+ * Makes sure that {@code parent/~~[randomStr]} directory doesn't exist.
+ * Notice that this method doesn't actually create any directory.
+ */
+ private static File getRandomDir(File parent) {
+ SecureRandom random = new SecureRandom();
+ byte[] bytes = new byte[16];
+ File dir;
+ do {
+ random.nextBytes(bytes);
+ String dirName = RANDOM_DIR_PREFIX
+ + Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP);
+ dir = new File(parent, dirName);
+ } while (dir.exists());
+ return dir;
+ }
+
+ private void addFileToMapLocked(File file, boolean deleteOldFile) {
+ final long version;
+ try {
+ version = mParser.getVersion(file);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to read font file", e);
+ return;
+ }
+ if (version == -1) {
+ Slog.e(TAG, "Invalid font file");
+ return;
+ }
+ FontFileInfo info = mFontFileInfoMap.get(file.getName());
+ if (info == null) {
+ // TODO: check version of font in /system/fonts and /product/fonts
+ mFontFileInfoMap.put(file.getName(), new FontFileInfo(file, version));
+ } else if (info.mVersion < version) {
+ if (deleteOldFile) {
+ FileUtils.deleteContentsAndDir(info.mFile.getParentFile());
+ }
+ mFontFileInfoMap.put(file.getName(), new FontFileInfo(file, version));
+ }
+ }
+
+ Map<String, File> getFontFileMap() {
+ Map<String, File> map = new HashMap<>();
+ synchronized (UpdatableFontDir.this) {
+ for (Map.Entry<String, FontFileInfo> entry : mFontFileInfoMap.entrySet()) {
+ map.put(entry.getKey(), entry.getValue().mFile);
+ }
+ }
+ return map;
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java b/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java
index a9eb75d..444d74d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecAtomWriter.java
@@ -38,10 +38,12 @@
* @param message The HDMI CEC message
* @param direction Whether the message is incoming, outgoing, or neither
* @param errorCode The error code from the final attempt to send the message
+ * @param callingUid The calling uid of the app that triggered this message
*/
- public void messageReported(HdmiCecMessage message, int direction, int errorCode) {
+ public void messageReported(
+ HdmiCecMessage message, int direction, int callingUid, int errorCode) {
MessageReportedGenericArgs genericArgs = createMessageReportedGenericArgs(
- message, direction, errorCode);
+ message, direction, errorCode, callingUid);
MessageReportedSpecialArgs specialArgs = createMessageReportedSpecialArgs(message);
messageReportedBase(genericArgs, specialArgs);
}
@@ -51,9 +53,10 @@
*
* @param message The HDMI CEC message
* @param direction Whether the message is incoming, outgoing, or neither
+ * @param callingUid The calling uid of the app that triggered this message
*/
- public void messageReported(HdmiCecMessage message, int direction) {
- messageReported(message, direction, ERROR_CODE_UNKNOWN);
+ public void messageReported(HdmiCecMessage message, int direction, int callingUid) {
+ messageReported(message, direction, callingUid, ERROR_CODE_UNKNOWN);
}
/**
@@ -65,11 +68,11 @@
* otherwise, ERROR_CODE_UNKNOWN
*/
private MessageReportedGenericArgs createMessageReportedGenericArgs(
- HdmiCecMessage message, int direction, int errorCode) {
+ HdmiCecMessage message, int direction, int errorCode, int callingUid) {
int sendMessageResult = errorCode == ERROR_CODE_UNKNOWN
? HdmiStatsEnums.SEND_MESSAGE_RESULT_UNKNOWN
: errorCode + 10;
- return new MessageReportedGenericArgs(direction, message.getSource(),
+ return new MessageReportedGenericArgs(callingUid, direction, message.getSource(),
message.getDestination(), message.getOpcode(), sendMessageResult);
}
@@ -134,7 +137,7 @@
MessageReportedSpecialArgs specialArgs) {
FrameworkStatsLog.write(
FrameworkStatsLog.HDMI_CEC_MESSAGE_REPORTED,
- 0, // Placeholder field
+ genericArgs.mUid,
genericArgs.mDirection,
genericArgs.mInitiatorLogicalAddress,
genericArgs.mDestinationLogicalAddress,
@@ -167,14 +170,16 @@
* Contains the required arguments for creating any HdmiCecMessageReported atom
*/
private class MessageReportedGenericArgs {
+ final int mUid;
final int mDirection;
final int mInitiatorLogicalAddress;
final int mDestinationLogicalAddress;
final int mOpcode;
final int mSendMessageResult;
- MessageReportedGenericArgs(int direction, int initiatorLogicalAddress,
+ MessageReportedGenericArgs(int uid, int direction, int initiatorLogicalAddress,
int destinationLogicalAddress, int opcode, int sendMessageResult) {
+ this.mUid = uid;
this.mDirection = direction;
this.mInitiatorLogicalAddress = initiatorLogicalAddress;
this.mDestinationLogicalAddress = destinationLogicalAddress;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index ddb0141..06bcada 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -28,6 +28,7 @@
import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.icu.util.IllformedLocaleException;
import android.icu.util.ULocale;
+import android.os.Binder;
import android.os.Handler;
import android.os.IHwBinder;
import android.os.Looper;
@@ -525,12 +526,14 @@
// Run a Runnable on IO thread.
// It should be careful to access member variables on IO thread because
// it can be accessed from system thread as well.
- private void runOnIoThread(Runnable runnable) {
- mIoHandler.post(runnable);
+ @VisibleForTesting
+ void runOnIoThread(Runnable runnable) {
+ mIoHandler.post(new WorkSourceUidPreservingRunnable(runnable));
}
- private void runOnServiceThread(Runnable runnable) {
- mControlHandler.post(runnable);
+ @VisibleForTesting
+ void runOnServiceThread(Runnable runnable) {
+ mControlHandler.post(new WorkSourceUidPreservingRunnable(runnable));
}
@ServiceThreadOnly
@@ -591,6 +594,18 @@
sendCommand(cecMessage, null);
}
+ /**
+ * Returns the calling UID of the original Binder call that triggered this code.
+ * If this code was not triggered by a Binder call, returns the UID of this process.
+ */
+ private int getCallingUid() {
+ int workSourceUid = Binder.getCallingWorkSourceUid();
+ if (workSourceUid == -1) {
+ return Binder.getCallingUid();
+ }
+ return workSourceUid;
+ }
+
@ServiceThreadOnly
void sendCommand(final HdmiCecMessage cecMessage,
final HdmiControlService.SendMessageCallback callback) {
@@ -621,6 +636,7 @@
mHdmiCecAtomWriter.messageReported(
cecMessage,
FrameworkStatsLog.HDMI_CEC_MESSAGE_REPORTED__DIRECTION__OUTGOING,
+ getCallingUid(),
finalError
);
if (callback != null) {
@@ -643,7 +659,7 @@
addCecMessageToHistory(true /* isReceived */, command);
mHdmiCecAtomWriter.messageReported(command,
- incomingMessageDirection(srcAddress, dstAddress));
+ incomingMessageDirection(srcAddress, dstAddress), getCallingUid());
onReceiveCommand(command);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index b78954dcb..b427bd0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -40,6 +40,7 @@
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiHotplugEvent;
import android.hardware.hdmi.HdmiPortInfo;
+import android.hardware.hdmi.IHdmiCecSettingChangeListener;
import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener;
import android.hardware.hdmi.IHdmiControlCallback;
import android.hardware.hdmi.IHdmiControlService;
@@ -74,6 +75,7 @@
import android.provider.Settings.Global;
import android.sysprop.HdmiProperties;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Slog;
import android.util.SparseArray;
@@ -308,6 +310,11 @@
private final ArrayList<VendorCommandListenerRecord> mVendorCommandListenerRecords =
new ArrayList<>();
+ // List of records for CEC setting change listener to handle the caller killed in action.
+ @GuardedBy("mLock")
+ private final ArrayMap<String, RemoteCallbackList<IHdmiCecSettingChangeListener>>
+ mHdmiCecSettingChangeListenerRecords = new ArrayMap<>();
+
@GuardedBy("mLock")
private InputChangeListenerRecord mInputChangeListenerRecord;
@@ -468,7 +475,9 @@
mPowerStatusController.setPowerStatus(getInitialPowerStatus());
mProhibitMode = false;
- mHdmiControlEnabled = readBooleanSetting(Global.HDMI_CONTROL_ENABLED, true);
+ mHdmiControlEnabled = mHdmiCecConfig.getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED)
+ == HdmiControlManager.HDMI_CEC_CONTROL_ENABLED;
mHdmiCecVolumeControlEnabled = readBooleanSetting(
Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED, true);
mMhlInputChangeEnabled = readBooleanSetting(Global.MHL_INPUT_SWITCHING_ENABLED, true);
@@ -498,7 +507,24 @@
if (mMessageValidator == null) {
mMessageValidator = new HdmiCecMessageValidator(this);
}
- mHdmiCecConfig.registerGlobalSettingsObserver(mIoLooper);
+ mHdmiCecConfig.registerGlobalSettingsObserver(mHandler.getLooper());
+ mHdmiCecConfig.registerChangeListener(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String setting) {
+ boolean enabled = mHdmiCecConfig.getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED)
+ == HdmiControlManager.HDMI_CEC_CONTROL_ENABLED;
+ setControlEnabled(enabled);
+ }
+ });
+ mHdmiCecConfig.registerChangeListener(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String setting) {
+ initializeCec(INITIATED_BY_ENABLE_CEC);
+ }
+ });
}
private void bootCompleted() {
@@ -623,9 +649,7 @@
private void registerContentObserver() {
ContentResolver resolver = getContext().getContentResolver();
String[] settings = new String[] {
- Global.HDMI_CONTROL_ENABLED,
Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
- Global.HDMI_CEC_VERSION,
Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
@@ -651,12 +675,6 @@
String option = uri.getLastPathSegment();
boolean enabled = readBooleanSetting(option, true);
switch (option) {
- case Global.HDMI_CONTROL_ENABLED:
- setControlEnabled(enabled);
- break;
- case Global.HDMI_CEC_VERSION:
- initializeCec(INITIATED_BY_ENABLE_CEC);
- break;
case Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED:
setHdmiCecVolumeControlEnabledInternal(enabled);
break;
@@ -991,12 +1009,14 @@
return mCecController.isConnected(portId);
}
+ /**
+ * Executes a Runnable on the service thread.
+ * During execution, sets the work source UID to the parent's work source UID.
+ *
+ * @param runnable The runnable to execute on the service thread
+ */
void runOnServiceThread(Runnable runnable) {
- mHandler.post(runnable);
- }
-
- void runOnServiceThreadAtFrontOfQueue(Runnable runnable) {
- mHandler.postAtFrontOfQueue(runnable);
+ mHandler.post(new WorkSourceUidPreservingRunnable(runnable));
}
private void assertRunOnServiceThread() {
@@ -1475,14 +1495,30 @@
}
}
+ /**
+ * Sets the work source UID to the Binder calling UID.
+ * Work source UID allows access to the original calling UID of a Binder call in the Runnables
+ * that it spawns.
+ * This is necessary because Runnables that are executed on the service thread
+ * take on the calling UID of the service thread.
+ */
+ private void setWorkSourceUidToCallingUid() {
+ Binder.setCallingWorkSourceUid(Binder.getCallingUid());
+ }
+
private void enforceAccessPermission() {
getContext().enforceCallingOrSelfPermission(PERMISSION, TAG);
}
+ private void initBinderCall() {
+ enforceAccessPermission();
+ setWorkSourceUidToCallingUid();
+ }
+
private final class BinderService extends IHdmiControlService.Stub {
@Override
public int[] getSupportedTypes() {
- enforceAccessPermission();
+ initBinderCall();
// mLocalDevices is an unmodifiable list - no lock necesary.
int[] localDevices = new int[mLocalDevices.size()];
for (int i = 0; i < localDevices.length; ++i) {
@@ -1494,14 +1530,14 @@
@Override
@Nullable
public HdmiDeviceInfo getActiveSource() {
- enforceAccessPermission();
+ initBinderCall();
return HdmiControlService.this.getActiveSource();
}
@Override
public void deviceSelect(final int deviceId, final IHdmiControlCallback callback) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1548,7 +1584,7 @@
@Override
public void portSelect(final int portId, final IHdmiControlCallback callback) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1586,7 +1622,7 @@
@Override
public void sendKeyEvent(final int deviceType, final int keyCode, final boolean isPressed) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1610,7 +1646,7 @@
@Override
public void sendVolumeKeyEvent(
final int deviceType, final int keyCode, final boolean isPressed) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1631,7 +1667,7 @@
@Override
public void oneTouchPlay(final IHdmiControlCallback callback) {
- enforceAccessPermission();
+ initBinderCall();
int pid = Binder.getCallingPid();
Slog.d(TAG, "Process pid: " + pid + " is calling oneTouchPlay.");
runOnServiceThread(new Runnable() {
@@ -1644,7 +1680,7 @@
@Override
public void toggleAndFollowTvPower() {
- enforceAccessPermission();
+ initBinderCall();
int pid = Binder.getCallingPid();
Slog.d(TAG, "Process pid: " + pid + " is calling toggleAndFollowTvPower.");
runOnServiceThread(new Runnable() {
@@ -1657,13 +1693,13 @@
@Override
public boolean shouldHandleTvPowerKey() {
- enforceAccessPermission();
+ initBinderCall();
return HdmiControlService.this.shouldHandleTvPowerKey();
}
@Override
public void queryDisplayStatus(final IHdmiControlCallback callback) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1675,53 +1711,53 @@
@Override
public void addHdmiControlStatusChangeListener(
final IHdmiControlStatusChangeListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.addHdmiControlStatusChangeListener(listener);
}
@Override
public void removeHdmiControlStatusChangeListener(
final IHdmiControlStatusChangeListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.removeHdmiControlStatusChangeListener(listener);
}
@Override
public void addHdmiCecVolumeControlFeatureListener(
final IHdmiCecVolumeControlFeatureListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.addHdmiCecVolumeControlFeatureListener(listener);
}
@Override
public void removeHdmiCecVolumeControlFeatureListener(
final IHdmiCecVolumeControlFeatureListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.removeHdmiControlVolumeControlStatusChangeListener(listener);
}
@Override
public void addHotplugEventListener(final IHdmiHotplugEventListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.addHotplugEventListener(listener);
}
@Override
public void removeHotplugEventListener(final IHdmiHotplugEventListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.removeHotplugEventListener(listener);
}
@Override
public void addDeviceEventListener(final IHdmiDeviceEventListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.addDeviceEventListener(listener);
}
@Override
public List<HdmiPortInfo> getPortInfo() {
- enforceAccessPermission();
+ initBinderCall();
return HdmiControlService.this.getPortInfo() == null
? Collections.<HdmiPortInfo>emptyList()
: HdmiControlService.this.getPortInfo();
@@ -1729,7 +1765,7 @@
@Override
public boolean canChangeSystemAudioMode() {
- enforceAccessPermission();
+ initBinderCall();
HdmiCecLocalDeviceTv tv = tv();
if (tv == null) {
return false;
@@ -1740,7 +1776,7 @@
@Override
public boolean getSystemAudioMode() {
// TODO(shubang): handle getSystemAudioMode() for all device types
- enforceAccessPermission();
+ initBinderCall();
HdmiCecLocalDeviceTv tv = tv();
HdmiCecLocalDeviceAudioSystem audioSystem = audioSystem();
return (tv != null && tv.isSystemAudioActivated())
@@ -1749,7 +1785,7 @@
@Override
public int getPhysicalAddress() {
- enforceAccessPermission();
+ initBinderCall();
synchronized (mLock) {
return mHdmiCecNetwork.getPhysicalAddress();
}
@@ -1757,7 +1793,7 @@
@Override
public void setSystemAudioMode(final boolean enabled, final IHdmiControlCallback callback) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1775,26 +1811,26 @@
@Override
public void addSystemAudioModeChangeListener(
final IHdmiSystemAudioModeChangeListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.addSystemAudioModeChangeListner(listener);
}
@Override
public void removeSystemAudioModeChangeListener(
final IHdmiSystemAudioModeChangeListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.removeSystemAudioModeChangeListener(listener);
}
@Override
public void setInputChangeListener(final IHdmiInputChangeListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.setInputChangeListener(listener);
}
@Override
public List<HdmiDeviceInfo> getInputDevices() {
- enforceAccessPermission();
+ initBinderCall();
// No need to hold the lock for obtaining TV device as the local device instance
// is preserved while the HDMI control is enabled.
return HdmiUtils.mergeToUnmodifiableList(mHdmiCecNetwork.getSafeExternalInputsLocked(),
@@ -1805,13 +1841,13 @@
// even those of reserved type.
@Override
public List<HdmiDeviceInfo> getDeviceList() {
- enforceAccessPermission();
+ initBinderCall();
return mHdmiCecNetwork.getSafeCecDevicesLocked();
}
@Override
public void powerOffRemoteDevice(int logicalAddress, int powerStatus) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1826,7 +1862,7 @@
@Override
public void powerOnRemoteDevice(int logicalAddress, int powerStatus) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1846,7 +1882,7 @@
@Override
// TODO(b/128427908): add a result callback
public void askRemoteDeviceToBecomeActiveSource(int physicalAddress) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1867,7 +1903,7 @@
@Override
public void setSystemAudioVolume(final int oldIndex, final int newIndex,
final int maxIndex) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1883,7 +1919,7 @@
@Override
public void setSystemAudioMute(final boolean mute) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1899,7 +1935,7 @@
@Override
public void setArcMode(final boolean enabled) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1914,7 +1950,7 @@
@Override
public void setProhibitMode(final boolean enabled) {
- enforceAccessPermission();
+ initBinderCall();
if (!isTvDevice()) {
return;
}
@@ -1924,14 +1960,14 @@
@Override
public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
final int deviceType) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.addVendorCommandListener(listener, deviceType);
}
@Override
public void sendVendorCommand(final int deviceType, final int targetAddress,
final byte[] params, final boolean hasVendorId) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1954,7 +1990,7 @@
@Override
public void sendStandby(final int deviceType, final int deviceId) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1978,13 +2014,13 @@
@Override
public void setHdmiRecordListener(IHdmiRecordListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.setHdmiRecordListener(listener);
}
@Override
public void startOneTouchRecord(final int recorderAddress, final byte[] recordSource) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -1999,7 +2035,7 @@
@Override
public void stopOneTouchRecord(final int recorderAddress) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -2015,7 +2051,7 @@
@Override
public void startTimerRecording(final int recorderAddress, final int sourceType,
final byte[] recordSource) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -2031,7 +2067,7 @@
@Override
public void clearTimerRecording(final int recorderAddress, final int sourceType,
final byte[] recordSource) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -2047,7 +2083,7 @@
@Override
public void sendMhlVendorCommand(final int portId, final int offset, final int length,
final byte[] data) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -2068,13 +2104,13 @@
@Override
public void addHdmiMhlVendorCommandListener(
IHdmiMhlVendorCommandListener listener) {
- enforceAccessPermission();
+ initBinderCall();
HdmiControlService.this.addHdmiMhlVendorCommandListener(listener);
}
@Override
public void setStandbyMode(final boolean isStandbyModeOn) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -2085,13 +2121,13 @@
@Override
public boolean isHdmiCecVolumeControlEnabled() {
- enforceAccessPermission();
+ initBinderCall();
return HdmiControlService.this.isHdmiCecVolumeControlEnabled();
}
@Override
public void setHdmiCecVolumeControlEnabled(final boolean isHdmiCecVolumeControlEnabled) {
- enforceAccessPermission();
+ initBinderCall();
final long token = Binder.clearCallingIdentity();
try {
HdmiControlService.this.setHdmiCecVolumeControlEnabled(
@@ -2104,7 +2140,7 @@
@Override
public void reportAudioStatus(final int deviceType, final int volume, final int maxVolume,
final boolean isMute) {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -2128,7 +2164,7 @@
@Override
public void setSystemAudioModeOnForAudioOnlySource() {
- enforceAccessPermission();
+ initBinderCall();
runOnServiceThread(new Runnable() {
@Override
public void run() {
@@ -2156,7 +2192,7 @@
@Nullable FileDescriptor err, String[] args,
@Nullable ShellCallback callback, ResultReceiver resultReceiver)
throws RemoteException {
- enforceAccessPermission();
+ initBinderCall();
new HdmiControlShellCommand(this)
.exec(this, in, out, err, args, callback, resultReceiver);
}
@@ -2211,8 +2247,22 @@
}
@Override
- public List<String> getUserCecSettings() {
+ public void addCecSettingChangeListener(String name,
+ final IHdmiCecSettingChangeListener listener) {
enforceAccessPermission();
+ HdmiControlService.this.addCecSettingChangeListener(name, listener);
+ }
+
+ @Override
+ public void removeCecSettingChangeListener(String name,
+ final IHdmiCecSettingChangeListener listener) {
+ enforceAccessPermission();
+ HdmiControlService.this.removeCecSettingChangeListener(name, listener);
+ }
+
+ @Override
+ public List<String> getUserCecSettings() {
+ initBinderCall();
long token = Binder.clearCallingIdentity();
try {
return HdmiControlService.this.getHdmiCecConfig().getUserSettings();
@@ -2223,7 +2273,7 @@
@Override
public List<String> getAllowedCecSettingStringValues(String name) {
- enforceAccessPermission();
+ initBinderCall();
long token = Binder.clearCallingIdentity();
try {
return HdmiControlService.this.getHdmiCecConfig().getAllowedStringValues(name);
@@ -2234,7 +2284,7 @@
@Override
public int[] getAllowedCecSettingIntValues(String name) {
- enforceAccessPermission();
+ initBinderCall();
long token = Binder.clearCallingIdentity();
try {
List<Integer> allowedValues =
@@ -2247,7 +2297,7 @@
@Override
public String getCecSettingStringValue(String name) {
- enforceAccessPermission();
+ initBinderCall();
long token = Binder.clearCallingIdentity();
try {
return HdmiControlService.this.getHdmiCecConfig().getStringValue(name);
@@ -2258,7 +2308,7 @@
@Override
public void setCecSettingStringValue(String name, String value) {
- enforceAccessPermission();
+ initBinderCall();
long token = Binder.clearCallingIdentity();
try {
HdmiControlService.this.getHdmiCecConfig().setStringValue(name, value);
@@ -2269,7 +2319,7 @@
@Override
public int getCecSettingIntValue(String name) {
- enforceAccessPermission();
+ initBinderCall();
long token = Binder.clearCallingIdentity();
try {
return HdmiControlService.this.getHdmiCecConfig().getIntValue(name);
@@ -2280,7 +2330,7 @@
@Override
public void setCecSettingIntValue(String name, int value) {
- enforceAccessPermission();
+ initBinderCall();
long token = Binder.clearCallingIdentity();
try {
HdmiControlService.this.getHdmiCecConfig().setIntValue(name, value);
@@ -3439,4 +3489,53 @@
protected HdmiCecConfig getHdmiCecConfig() {
return mHdmiCecConfig;
}
+
+ private HdmiCecConfig.SettingChangeListener mSettingChangeListener =
+ new HdmiCecConfig.SettingChangeListener() {
+ @Override
+ public void onChange(String name) {
+ synchronized (mLock) {
+ if (!mHdmiCecSettingChangeListenerRecords.containsKey(name)) {
+ return;
+ }
+ mHdmiCecSettingChangeListenerRecords.get(name).broadcast(listener -> {
+ invokeCecSettingChangeListenerLocked(name, listener);
+ });
+ }
+ }
+ };
+
+ private void addCecSettingChangeListener(String name,
+ final IHdmiCecSettingChangeListener listener) {
+ synchronized (mLock) {
+ if (!mHdmiCecSettingChangeListenerRecords.containsKey(name)) {
+ mHdmiCecSettingChangeListenerRecords.put(name, new RemoteCallbackList<>());
+ mHdmiCecConfig.registerChangeListener(name, mSettingChangeListener);
+ }
+ mHdmiCecSettingChangeListenerRecords.get(name).register(listener);
+ }
+ }
+
+ private void removeCecSettingChangeListener(String name,
+ final IHdmiCecSettingChangeListener listener) {
+ synchronized (mLock) {
+ if (!mHdmiCecSettingChangeListenerRecords.containsKey(name)) {
+ return;
+ }
+ mHdmiCecSettingChangeListenerRecords.get(name).unregister(listener);
+ if (mHdmiCecSettingChangeListenerRecords.get(name).getRegisteredCallbackCount() == 0) {
+ mHdmiCecSettingChangeListenerRecords.remove(name);
+ mHdmiCecConfig.removeChangeListener(name, mSettingChangeListener);
+ }
+ }
+ }
+
+ private void invokeCecSettingChangeListenerLocked(String name,
+ final IHdmiCecSettingChangeListener listener) {
+ try {
+ listener.onChange(name);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to report setting change", e);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/WorkSourceUidPreservingRunnable.java b/services/core/java/com/android/server/hdmi/WorkSourceUidPreservingRunnable.java
new file mode 100644
index 0000000..afccd88
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/WorkSourceUidPreservingRunnable.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.os.Binder;
+
+/**
+ * Executes a given Runnable with the work source UID of the thread that constructed this.
+ */
+public class WorkSourceUidPreservingRunnable implements Runnable {
+ private Runnable mRunnable;
+ private int mUid;
+
+ /**
+ * @param runnable The Runnable to execute
+ */
+ public WorkSourceUidPreservingRunnable(Runnable runnable) {
+ this.mRunnable = runnable;
+ this.mUid = Binder.getCallingWorkSourceUid();
+ }
+
+ @Override
+ public void run() {
+ long token = Binder.setCallingWorkSourceUid(mUid);
+ try {
+ mRunnable.run();
+ } finally {
+ Binder.restoreCallingWorkSource(token);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 71fcd1d..3e0d040 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -235,10 +235,6 @@
IInputFilter mInputFilter; // guarded by mInputFilterLock
InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
- private final Object mGestureMonitorPidsLock = new Object();
- @GuardedBy("mGestureMonitorPidsLock")
- private final ArrayMap<IBinder, Integer> mGestureMonitorPidsByToken = new ArrayMap<>();
-
// The associations of input devices to displays by port. Maps from input device port (String)
// to display id (int). Currently only accessed by InputReader.
private final Map<String, Integer> mStaticAssociations;
@@ -640,9 +636,6 @@
InputChannel inputChannel = nativeCreateInputMonitor(
mPtr, displayId, true /*isGestureMonitor*/, inputChannelName, pid);
InputMonitorHost host = new InputMonitorHost(inputChannel.getToken());
- synchronized (mGestureMonitorPidsLock) {
- mGestureMonitorPidsByToken.put(inputChannel.getToken(), pid);
- }
return new InputMonitor(inputChannel, host);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -666,9 +659,6 @@
if (connectionToken == null) {
throw new IllegalArgumentException("connectionToken must not be null.");
}
- synchronized (mGestureMonitorPidsLock) {
- mGestureMonitorPidsByToken.remove(connectionToken);
- }
nativeRemoveInputChannel(mPtr, connectionToken);
}
@@ -2069,8 +2059,7 @@
@Override // Binder call
public InputSensorInfo[] getSensorList(int deviceId) {
- InputSensorInfo[] sensors = nativeGetSensorList(mPtr, deviceId);
- return sensors;
+ return nativeGetSensorList(mPtr, deviceId);
}
@Override // Binder call
@@ -2167,7 +2156,6 @@
if (dumpStr != null) {
pw.println(dumpStr);
dumpAssociations(pw);
- dumpGestureMonitorPidsByToken(pw);
}
}
@@ -2191,19 +2179,6 @@
}
}
- private void dumpGestureMonitorPidsByToken(PrintWriter pw) {
- synchronized (mGestureMonitorPidsLock) {
- if (!mGestureMonitorPidsByToken.isEmpty()) {
- pw.println("Gesture monitor pids by token:");
- for (int i = 0; i < mGestureMonitorPidsByToken.size(); i++) {
- pw.print(" " + i + ": ");
- pw.print(" token: " + mGestureMonitorPidsByToken.keyAt(i));
- pw.println(" pid: " + mGestureMonitorPidsByToken.valueAt(i));
- }
- }
- }
- }
-
private boolean checkCallingPermission(String permission, String func) {
// Quick check: if the calling permission is me, it's all okay.
if (Binder.getCallingPid() == Process.myPid()) {
@@ -2226,7 +2201,6 @@
public void monitor() {
synchronized (mInputFilterLock) { }
synchronized (mAssociationsLock) { /* Test if blocked by associations lock. */}
- synchronized (mGestureMonitorPidsLock) { /* Test if blocked by gesture monitor pids lock */}
synchronized (mLidSwitchLock) { /* Test if blocked by lid switch lock. */ }
nativeMonitor(mPtr);
}
@@ -2296,9 +2270,6 @@
// Native callback.
private void notifyInputChannelBroken(IBinder token) {
- synchronized (mGestureMonitorPidsLock) {
- mGestureMonitorPidsByToken.remove(token);
- }
mWindowManagerCallbacks.notifyInputChannelBroken(token);
}
@@ -2328,33 +2299,25 @@
}
// Native callback
- private void notifyConnectionUnresponsive(IBinder token, String reason) {
- Integer gestureMonitorPid;
- synchronized (mGestureMonitorPidsLock) {
- gestureMonitorPid = mGestureMonitorPidsByToken.get(token);
- }
- if (gestureMonitorPid != null) {
- mWindowManagerCallbacks.notifyGestureMonitorUnresponsive(gestureMonitorPid, reason);
- return;
- }
- // If we couldn't find a gesture monitor for this token, it's a window
+ private void notifyWindowUnresponsive(IBinder token, String reason) {
mWindowManagerCallbacks.notifyWindowUnresponsive(token, reason);
}
// Native callback
- private void notifyConnectionResponsive(IBinder token) {
- Integer gestureMonitorPid;
- synchronized (mGestureMonitorPidsLock) {
- gestureMonitorPid = mGestureMonitorPidsByToken.get(token);
- }
- if (gestureMonitorPid != null) {
- mWindowManagerCallbacks.notifyGestureMonitorResponsive(gestureMonitorPid);
- return;
- }
- // If we couldn't find a gesture monitor for this token, it's a window
+ private void notifyMonitorUnresponsive(int pid, String reason) {
+ mWindowManagerCallbacks.notifyGestureMonitorUnresponsive(pid, reason);
+ }
+
+ // Native callback
+ private void notifyWindowResponsive(IBinder token) {
mWindowManagerCallbacks.notifyWindowResponsive(token);
}
+ // Native callback
+ private void notifyMonitorResponsive(int pid) {
+ mWindowManagerCallbacks.notifyGestureMonitorResponsive(pid);
+ }
+
// Native callback.
private void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp,
float[] values) {
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index e8052289..83b6eca 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -807,22 +807,7 @@
@Override
public LocationTime getGnssTimeMillis() {
- synchronized (mLock) {
- LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER);
- if (gpsManager == null) {
- return null;
- }
-
- Location location = gpsManager.getLastLocationUnsafe(UserHandle.USER_ALL,
- PERMISSION_FINE, false, Long.MAX_VALUE);
- if (location == null) {
- return null;
- }
-
- long currentNanos = SystemClock.elapsedRealtimeNanos();
- long deltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeAgeNanos(currentNanos));
- return new LocationTime(location.getTime() + deltaMs, currentNanos);
- }
+ return mLocalService.getGnssTimeMillis();
}
@Override
@@ -1292,6 +1277,25 @@
mGnssManagerService.sendNiResponse(notifId, userResponse);
}
}
+
+ @Override
+ public @Nullable LocationTime getGnssTimeMillis() {
+ LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER);
+ if (gpsManager == null) {
+ return null;
+ }
+
+ Location location = gpsManager.getLastLocationUnsafe(UserHandle.USER_ALL,
+ PERMISSION_FINE, false, Long.MAX_VALUE);
+ if (location == null) {
+ return null;
+ }
+
+ long currentNanos = SystemClock.elapsedRealtimeNanos();
+ long deltaMs = NANOSECONDS.toMillis(
+ location.getElapsedRealtimeAgeNanos(currentNanos));
+ return new LocationTime(location.getTime() + deltaMs, currentNanos);
+ }
}
private static class SystemInjector implements Injector {
diff --git a/services/core/java/com/android/server/location/LocationShellCommand.java b/services/core/java/com/android/server/location/LocationShellCommand.java
index 0fe66e0..f0dd8b5 100644
--- a/services/core/java/com/android/server/location/LocationShellCommand.java
+++ b/services/core/java/com/android/server/location/LocationShellCommand.java
@@ -49,6 +49,12 @@
}
switch (cmd) {
+ case "is-location-enabled": {
+ int userId = parseUserId();
+ boolean enabled = mService.isLocationEnabledForUser(userId);
+ getOutPrintWriter().println(enabled);
+ return 0;
+ }
case "set-location-enabled": {
int userId = parseUserId();
boolean enabled = Boolean.parseBoolean(getNextArgRequired());
@@ -238,6 +244,8 @@
pw.println("Location service commands:");
pw.println(" help or -h");
pw.println(" Print this help text.");
+ pw.println(" is-location-enabled [--user <USER_ID>]");
+ pw.println(" Gets the master location switch enabled state.");
pw.println(" set-location-enabled [--user <USER_ID>] true|false");
pw.println(" Sets the master location switch enabled state.");
pw.println(" providers");
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 63a42f8..dc1a26a 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
+import android.hardware.SensorPrivacyManager;
import android.hardware.contexthub.V1_0.AsyncEventType;
import android.hardware.contexthub.V1_0.ContextHub;
import android.hardware.contexthub.V1_0.ContextHubMsg;
@@ -117,6 +118,9 @@
// True if WiFi is available for the Context Hub
private boolean mIsWifiAvailable = false;
+ // True if audio is disabled for the ContextHub
+ private boolean mIsAudioDisabled = false;
+
// Lock object for sendWifiSettingUpdate()
private final Object mSendWifiSettingUpdateLock = new Object();
@@ -256,6 +260,21 @@
}
}, UserHandle.USER_ALL);
}
+
+ if (mContextHubWrapper.supportsMicrophoneDisableSettingNotifications()) {
+ sendMicrophoneDisableSettingUpdate();
+
+ SensorPrivacyManager.OnSensorPrivacyChangedListener listener =
+ new SensorPrivacyManager.OnSensorPrivacyChangedListener() {
+ @Override
+ public void onSensorPrivacyChanged(boolean enabled) {
+ sendMicrophoneDisableSettingUpdate();
+ }
+ };
+ SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
+ manager.addSensorPrivacyListener(
+ SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE, listener);
+ }
}
/**
@@ -999,6 +1018,21 @@
mContextHubWrapper.onAirplaneModeSettingChanged(enabled);
}
+ /**
+ * Obtains the latest microphone disable setting value and notifies the
+ * Context Hub.
+ */
+ private void sendMicrophoneDisableSettingUpdate() {
+ SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
+ boolean disabled = manager.isIndividualSensorPrivacyEnabled(
+ SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE);
+ if (mIsAudioDisabled != disabled) {
+ mIsAudioDisabled = disabled;
+ mContextHubWrapper.onMicrophoneDisableSettingChanged(disabled);
+ }
+ }
+
+
private String getCallingPackageName() {
return mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
}
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index 4242d72..c11e289 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -129,6 +129,18 @@
*/
public abstract void onAirplaneModeSettingChanged(boolean enabled);
+ /**
+ * @return True if this version of the Contexthub HAL supports microphone
+ * disable setting notifications.
+ */
+ public abstract boolean supportsMicrophoneDisableSettingNotifications();
+
+ /**
+ * Notifies the Contexthub implementation of a microphone disable setting
+ * change.
+ */
+ public abstract void onMicrophoneDisableSettingChanged(boolean enabled);
+
private static class ContextHubWrapperV1_0 extends IContextHubWrapper {
private android.hardware.contexthub.V1_0.IContexthub mHub;
@@ -152,6 +164,10 @@
return false;
}
+ public boolean supportsMicrophoneDisableSettingNotifications() {
+ return false;
+ }
+
public void onLocationSettingChanged(boolean enabled) {
}
@@ -160,6 +176,9 @@
public void onAirplaneModeSettingChanged(boolean enabled) {
}
+
+ public void onMicrophoneDisableSettingChanged(boolean enabled) {
+ }
}
private static class ContextHubWrapperV1_1 extends IContextHubWrapper {
@@ -185,6 +204,10 @@
return false;
}
+ public boolean supportsMicrophoneDisableSettingNotifications() {
+ return false;
+ }
+
public void onLocationSettingChanged(boolean enabled) {
try {
mHub.onSettingChanged(Setting.LOCATION,
@@ -199,6 +222,9 @@
public void onAirplaneModeSettingChanged(boolean enabled) {
}
+
+ public void onMicrophoneDisableSettingChanged(boolean enabled) {
+ }
}
private static class ContextHubWrapperV1_2 extends IContextHubWrapper {
@@ -224,6 +250,10 @@
return true;
}
+ public boolean supportsMicrophoneDisableSettingNotifications() {
+ return true;
+ }
+
public void onLocationSettingChanged(boolean enabled) {
sendSettingChanged(Setting.LOCATION,
enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
@@ -239,6 +269,11 @@
enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
}
+ public void onMicrophoneDisableSettingChanged(boolean enabled) {
+ sendSettingChanged(android.hardware.contexthub.V1_2.Setting.GLOBAL_MIC_DISABLE,
+ enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
+ }
+
private void sendSettingChanged(byte setting, byte newValue) {
try {
mHub.onSettingChanged_1_2(setting, newValue);
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 92957aa..b6695c2 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -193,7 +193,9 @@
IGnssMeasurementsListener listener, String packageName,
@Nullable String attributionTag) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
-
+ if (request.isCorrelationVectorOutputsEnabled()) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
+ }
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
mGnssMeasurementsProvider.addListener(request, identity, listener);
}
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index b623e27..305bc9b 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -118,7 +118,8 @@
@Override
protected boolean registerWithService(GnssMeasurementRequest request,
Collection<GnssListenerRegistration> registrations) {
- if (mGnssNative.startMeasurementCollection(request.isFullTracking())) {
+ if (mGnssNative.startMeasurementCollection(request.isFullTracking(),
+ request.isCorrelationVectorOutputsEnabled())) {
if (D) {
Log.d(TAG, "starting gnss measurements (" + request + ")");
}
@@ -160,18 +161,26 @@
protected GnssMeasurementRequest mergeRegistrations(
Collection<GnssListenerRegistration> registrations) {
boolean fullTracking = false;
+ boolean enableCorrVecOutputs = false;
+
if (mSettingsHelper.isGnssMeasurementsFullTrackingEnabled()) {
fullTracking = true;
- } else {
- for (GnssListenerRegistration registration : registrations) {
- if (registration.getRequest().isFullTracking()) {
- fullTracking = true;
- break;
- }
+ }
+
+ for (GnssListenerRegistration registration : registrations) {
+ GnssMeasurementRequest request = registration.getRequest();
+ if (request.isFullTracking()) {
+ fullTracking = true;
+ }
+ if (request.isCorrelationVectorOutputsEnabled()) {
+ enableCorrVecOutputs = true;
}
}
- return new GnssMeasurementRequest.Builder().setFullTracking(fullTracking).build();
+ return new GnssMeasurementRequest.Builder()
+ .setFullTracking(fullTracking)
+ .setCorrelationVectorOutputsEnabled(enableCorrVecOutputs)
+ .build();
}
@Override
diff --git a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
index 402e84b..7e2f089 100644
--- a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
+++ b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
@@ -733,9 +733,10 @@
/**
* Starts measurement collection.
*/
- public boolean startMeasurementCollection(boolean enableFullTracking) {
+ public boolean startMeasurementCollection(boolean enableFullTracking,
+ boolean enableCorrVecOutputs) {
Preconditions.checkState(mRegistered);
- return mGnssHal.startMeasurementCollection(enableFullTracking);
+ return mGnssHal.startMeasurementCollection(enableFullTracking, enableCorrVecOutputs);
}
/**
@@ -1274,8 +1275,9 @@
return native_is_measurement_supported();
}
- protected boolean startMeasurementCollection(boolean enableFullTracking) {
- return native_start_measurement_collection(enableFullTracking);
+ protected boolean startMeasurementCollection(boolean enableFullTracking,
+ boolean enableCorrVecOutputs) {
+ return native_start_measurement_collection(enableFullTracking, enableCorrVecOutputs);
}
protected boolean stopMeasurementCollection() {
@@ -1438,7 +1440,8 @@
private static native boolean native_is_measurement_supported();
- private static native boolean native_start_measurement_collection(boolean enableFullTracking);
+ private static native boolean native_start_measurement_collection(boolean enableFullTracking,
+ boolean enableCorrVecOutputs);
private static native boolean native_stop_measurement_collection();
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 14f0100..b06389a 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -18,7 +18,6 @@
import static android.app.compat.CompatChanges.isChangeEnabled;
import static android.location.LocationManager.DELIVER_HISTORICAL_LOCATIONS;
-import static android.location.LocationManager.FUSED_PROVIDER;
import static android.location.LocationManager.GPS_PROVIDER;
import static android.location.LocationManager.KEY_FLUSH_COMPLETE;
import static android.location.LocationManager.KEY_LOCATION_CHANGED;
@@ -43,6 +42,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.AlarmManager.OnAlarmListener;
+import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
@@ -86,7 +86,6 @@
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
-import com.android.server.PendingIntentUtils;
import com.android.server.location.LocationPermissions;
import com.android.server.location.LocationPermissions.PermissionLevel;
import com.android.server.location.fudger.LocationFudger;
@@ -131,6 +130,9 @@
private static final String WAKELOCK_TAG = "*location*";
private static final long WAKELOCK_TIMEOUT_MS = 30 * 1000;
+ // duration PI location clients are put on the allowlist to start a fg service
+ private static final long TEMPORARY_APP_ALLOWLIST_DURATION_MS = 10 * 1000;
+
// fastest interval at which clients may receive coarse locations
private static final long MIN_COARSE_INTERVAL_MS = 10 * 60 * 1000;
@@ -215,6 +217,11 @@
public void deliverOnLocationChanged(LocationResult locationResult,
@Nullable Runnable onCompleteCallback)
throws PendingIntent.CanceledException {
+ BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setDontSendToRestrictedApps(true);
+ // allows apps to start a fg service in response to a location PI
+ options.setTemporaryAppWhitelistDuration(TEMPORARY_APP_ALLOWLIST_DURATION_MS);
+
mPendingIntent.send(
mContext,
0,
@@ -225,22 +232,26 @@
: null,
null,
null,
- PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
+ options.toBundle());
}
@Override
public void deliverOnFlushComplete(int requestCode) throws PendingIntent.CanceledException {
+ BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setDontSendToRestrictedApps(true);
+
mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_FLUSH_COMPLETE, requestCode),
- null, null, null,
- PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
+ null, null, null, options.toBundle());
}
@Override
public void deliverOnProviderEnabledChanged(String provider, boolean enabled)
throws PendingIntent.CanceledException {
+ BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setDontSendToRestrictedApps(true);
+
mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_PROVIDER_ENABLED, enabled),
- null, null, null,
- PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
+ null, null, null, options.toBundle());
}
}
@@ -2332,8 +2343,8 @@
// do not send change notifications if we just saw this user for the first time
if (wasEnabled != null) {
- // fused and passive provider never get public updates for legacy reasons
- if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
+ // passive provider never get public updates for legacy reasons
+ if (!PASSIVE_PROVIDER.equals(mName)) {
Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
.putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
diff --git a/services/core/java/com/android/server/locksettings/AesEncryptionUtil.java b/services/core/java/com/android/server/locksettings/AesEncryptionUtil.java
new file mode 100644
index 0000000..8e7e419
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/AesEncryptionUtil.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
+class AesEncryptionUtil {
+ /** The algorithm used for the encryption of the key blob. */
+ private static final String CIPHER_ALGO = "AES/GCM/NoPadding";
+
+ private AesEncryptionUtil() {}
+
+ static byte[] decrypt(SecretKey key, DataInputStream cipherStream) throws IOException {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(cipherStream);
+
+ int ivSize = cipherStream.readInt();
+ if (ivSize < 0 || ivSize > 32) {
+ throw new IOException("IV out of range: " + ivSize);
+ }
+ byte[] iv = new byte[ivSize];
+ cipherStream.readFully(iv);
+
+ int rawCipherTextSize = cipherStream.readInt();
+ if (rawCipherTextSize < 0) {
+ throw new IOException("Invalid cipher text size: " + rawCipherTextSize);
+ }
+
+ byte[] rawCipherText = new byte[rawCipherTextSize];
+ cipherStream.readFully(rawCipherText);
+
+ final byte[] plainText;
+ try {
+ Cipher c = Cipher.getInstance(CIPHER_ALGO);
+ c.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));
+ plainText = c.doFinal(rawCipherText);
+ } catch (NoSuchAlgorithmException | InvalidKeyException | BadPaddingException
+ | IllegalBlockSizeException | NoSuchPaddingException
+ | InvalidAlgorithmParameterException e) {
+ throw new IOException("Could not decrypt cipher text", e);
+ }
+
+ return plainText;
+ }
+
+ static byte[] decrypt(SecretKey key, byte[] cipherText) throws IOException {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(cipherText);
+
+ DataInputStream cipherStream = new DataInputStream(new ByteArrayInputStream(cipherText));
+ return decrypt(key, cipherStream);
+ }
+
+ static byte[] encrypt(SecretKey key, byte[] plainText) throws IOException {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(plainText);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ DataOutputStream dos = new DataOutputStream(bos);
+
+ final byte[] cipherText;
+ final byte[] iv;
+ try {
+ Cipher cipher = Cipher.getInstance(CIPHER_ALGO);
+ cipher.init(Cipher.ENCRYPT_MODE, key);
+ cipherText = cipher.doFinal(plainText);
+ iv = cipher.getIV();
+ } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException
+ | NoSuchPaddingException | InvalidKeyException e) {
+ throw new IOException("Could not encrypt input data", e);
+ }
+
+ dos.writeInt(iv.length);
+ dos.write(iv);
+ dos.writeInt(cipherText.length);
+ dos.write(cipherText);
+
+ return bos.toByteArray();
+ }
+}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index f7f3440..9f351a3 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -643,7 +643,7 @@
unlockIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
showEncryptionNotification(user, title, message, detail, intent);
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 5d0544b..7dd961a 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -753,8 +753,9 @@
pw.increaseIndent();
File[] files = userPath.listFiles();
if (files != null) {
+ Arrays.sort(files);
for (File file : files) {
- pw.println(String.format("%4d %s %s", file.length(),
+ pw.println(String.format("%6d %s %s", file.length(),
LockSettingsService.timestampToString(file.lastModified()),
file.getName()));
}
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowData.java b/services/core/java/com/android/server/locksettings/RebootEscrowData.java
index 2b19079..38eeb88 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowData.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowData.java
@@ -16,22 +16,14 @@
package com.android.server.locksettings;
-import com.android.internal.util.Preconditions;
-
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
+import java.util.Objects;
-import javax.crypto.BadPaddingException;
-import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.NoSuchPaddingException;
-import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.SecretKey;
/**
* Holds the data necessary to complete a reboot escrow of the Synthetic Password.
@@ -41,22 +33,17 @@
* This is the current version of the escrow data format. This should be incremented if the
* format on disk is changed.
*/
- private static final int CURRENT_VERSION = 1;
+ private static final int CURRENT_VERSION = 2;
- /** The algorithm used for the encryption of the key blob. */
- private static final String CIPHER_ALGO = "AES/GCM/NoPadding";
-
- private RebootEscrowData(byte spVersion, byte[] iv, byte[] syntheticPassword, byte[] blob,
+ private RebootEscrowData(byte spVersion, byte[] syntheticPassword, byte[] blob,
RebootEscrowKey key) {
mSpVersion = spVersion;
- mIv = iv;
mSyntheticPassword = syntheticPassword;
mBlob = blob;
mKey = key;
}
private final byte mSpVersion;
- private final byte[] mIv;
private final byte[] mSyntheticPassword;
private final byte[] mBlob;
private final RebootEscrowKey mKey;
@@ -65,10 +52,6 @@
return mSpVersion;
}
- public byte[] getIv() {
- return mIv;
- }
-
public byte[] getSyntheticPassword() {
return mSyntheticPassword;
}
@@ -81,76 +64,43 @@
return mKey;
}
- static RebootEscrowData fromEncryptedData(RebootEscrowKey key, byte[] blob)
+ static RebootEscrowData fromEncryptedData(RebootEscrowKey ks, byte[] blob, SecretKey kk)
throws IOException {
- Preconditions.checkNotNull(key);
- Preconditions.checkNotNull(blob);
+ Objects.requireNonNull(ks);
+ Objects.requireNonNull(blob);
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(blob));
int version = dis.readInt();
if (version != CURRENT_VERSION) {
throw new IOException("Unsupported version " + version);
}
-
byte spVersion = dis.readByte();
- int ivSize = dis.readInt();
- if (ivSize < 0 || ivSize > 32) {
- throw new IOException("IV out of range: " + ivSize);
- }
- byte[] iv = new byte[ivSize];
- dis.readFully(iv);
+ // Decrypt the blob with the key from keystore first, then decrypt again with the reboot
+ // escrow key.
+ byte[] ksEncryptedBlob = AesEncryptionUtil.decrypt(kk, dis);
+ final byte[] syntheticPassword = AesEncryptionUtil.decrypt(ks.getKey(), ksEncryptedBlob);
- int cipherTextSize = dis.readInt();
- if (cipherTextSize < 0) {
- throw new IOException("Invalid cipher text size: " + cipherTextSize);
- }
-
- byte[] cipherText = new byte[cipherTextSize];
- dis.readFully(cipherText);
-
- final byte[] syntheticPassword;
- try {
- Cipher c = Cipher.getInstance(CIPHER_ALGO);
- c.init(Cipher.DECRYPT_MODE, key.getKey(), new IvParameterSpec(iv));
- syntheticPassword = c.doFinal(cipherText);
- } catch (NoSuchAlgorithmException | InvalidKeyException | BadPaddingException
- | IllegalBlockSizeException | NoSuchPaddingException
- | InvalidAlgorithmParameterException e) {
- throw new IOException("Could not decrypt ciphertext", e);
- }
-
- return new RebootEscrowData(spVersion, iv, syntheticPassword, blob, key);
+ return new RebootEscrowData(spVersion, syntheticPassword, blob, ks);
}
- static RebootEscrowData fromSyntheticPassword(RebootEscrowKey key, byte spVersion,
- byte[] syntheticPassword)
+ static RebootEscrowData fromSyntheticPassword(RebootEscrowKey ks, byte spVersion,
+ byte[] syntheticPassword, SecretKey kk)
throws IOException {
- Preconditions.checkNotNull(syntheticPassword);
+ Objects.requireNonNull(syntheticPassword);
+
+ // Encrypt synthetic password with the escrow key first; then encrypt the blob again with
+ // the key from keystore.
+ byte[] ksEncryptedBlob = AesEncryptionUtil.encrypt(ks.getKey(), syntheticPassword);
+ byte[] kkEncryptedBlob = AesEncryptionUtil.encrypt(kk, ksEncryptedBlob);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
- final byte[] cipherText;
- final byte[] iv;
- try {
- Cipher cipher = Cipher.getInstance(CIPHER_ALGO);
- cipher.init(Cipher.ENCRYPT_MODE, key.getKey());
- cipherText = cipher.doFinal(syntheticPassword);
- iv = cipher.getIV();
- } catch (NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException
- | NoSuchPaddingException | InvalidKeyException e) {
- throw new IOException("Could not encrypt reboot escrow data", e);
- }
-
dos.writeInt(CURRENT_VERSION);
dos.writeByte(spVersion);
- dos.writeInt(iv.length);
- dos.write(iv);
- dos.writeInt(cipherText.length);
- dos.write(cipherText);
+ dos.write(kkEncryptedBlob);
- return new RebootEscrowData(spVersion, iv, syntheticPassword, bos.toByteArray(),
- key);
+ return new RebootEscrowData(spVersion, syntheticPassword, bos.toByteArray(), ks);
}
}
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowKeyStoreManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowKeyStoreManager.java
new file mode 100644
index 0000000..bae029c
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowKeyStoreManager.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings;
+
+import android.security.keystore.AndroidKeyStoreSpi;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
+import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
+import android.security.keystore2.AndroidKeyStoreProvider;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+/**
+ * This class loads and generates the key used for resume on reboot from android keystore.
+ */
+public class RebootEscrowKeyStoreManager {
+ private static final String TAG = "RebootEscrowKeyStoreManager";
+
+ /**
+ * The key alias in keystore. This key is used to wrap both escrow key and escrow data.
+ */
+ public static final String REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME =
+ "reboot_escrow_key_store_encryption_key";
+
+ public static final int KEY_LENGTH = 256;
+
+ /**
+ * Use keystore2 once it's installed.
+ */
+ private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeystore";
+
+ /**
+ * The selinux namespace for resume_on_reboot_key
+ */
+ private static final int KEY_STORE_NAMESPACE = 120;
+
+ /**
+ * Hold this lock when getting or generating the encryption key in keystore.
+ */
+ private final Object mKeyStoreLock = new Object();
+
+ @GuardedBy("mKeyStoreLock")
+ private SecretKey getKeyStoreEncryptionKeyLocked() {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
+ KeyStore.LoadStoreParameter loadStoreParameter = null;
+ // Load from the specific namespace if keystore2 is enabled.
+ if (AndroidKeyStoreProvider.isInstalled()) {
+ loadStoreParameter = new AndroidKeyStoreLoadStoreParameter(KEY_STORE_NAMESPACE);
+ }
+ keyStore.load(loadStoreParameter);
+ return (SecretKey) keyStore.getKey(REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME,
+ null);
+ } catch (IOException | GeneralSecurityException e) {
+ Slog.e(TAG, "Unable to get encryption key from keystore.", e);
+ }
+ return null;
+ }
+
+ protected SecretKey getKeyStoreEncryptionKey() {
+ synchronized (mKeyStoreLock) {
+ return getKeyStoreEncryptionKeyLocked();
+ }
+ }
+
+ protected void clearKeyStoreEncryptionKey() {
+ synchronized (mKeyStoreLock) {
+ try {
+ KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER);
+ KeyStore.LoadStoreParameter loadStoreParameter = null;
+ // Load from the specific namespace if keystore2 is enabled.
+ if (AndroidKeyStoreProvider.isInstalled()) {
+ loadStoreParameter = new AndroidKeyStoreLoadStoreParameter(KEY_STORE_NAMESPACE);
+ }
+ keyStore.load(loadStoreParameter);
+ keyStore.deleteEntry(REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME);
+ } catch (IOException | GeneralSecurityException e) {
+ Slog.e(TAG, "Unable to delete encryption key in keystore.", e);
+ }
+ }
+ }
+
+ protected SecretKey generateKeyStoreEncryptionKeyIfNeeded() {
+ synchronized (mKeyStoreLock) {
+ SecretKey kk = getKeyStoreEncryptionKeyLocked();
+ if (kk != null) {
+ return kk;
+ }
+
+ try {
+ KeyGenerator generator = KeyGenerator.getInstance(
+ KeyProperties.KEY_ALGORITHM_AES, AndroidKeyStoreSpi.NAME);
+ KeyGenParameterSpec.Builder parameterSpecBuilder = new KeyGenParameterSpec.Builder(
+ REBOOT_ESCROW_KEY_STORE_ENCRYPTION_KEY_NAME,
+ KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setKeySize(KEY_LENGTH)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE);
+ // Generate the key with the correct namespace if keystore2 is enabled.
+ if (AndroidKeyStoreProvider.isInstalled()) {
+ parameterSpecBuilder.setNamespace(KEY_STORE_NAMESPACE);
+ }
+ generator.init(parameterSpecBuilder.build());
+ return generator.generateKey();
+ } catch (GeneralSecurityException e) {
+ // Should never happen.
+ Slog.e(TAG, "Unable to generate key from keystore.", e);
+ }
+ return null;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index 8d5f553..fbec915 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -40,6 +40,18 @@
import java.util.List;
import java.util.Locale;
+import javax.crypto.SecretKey;
+
+/**
+ * This class aims to persists the synthetic password(SP) across reboot in a secure way. In
+ * particular, it manages the encryption of the sp before reboot, and decryption of the sp after
+ * reboot. Here are the meaning of some terms.
+ * SP: synthetic password
+ * K_s: The RebootEscrowKey, i.e. AES-GCM key stored in memory
+ * K_k: AES-GCM key in android keystore
+ * RebootEscrowData: The synthetic password and its encrypted blob. We encrypt SP with K_s first,
+ * then with K_k, i.e. E(K_k, E(K_s, SP))
+ */
class RebootEscrowManager {
private static final String TAG = "RebootEscrowManager";
@@ -101,6 +113,8 @@
private final Callbacks mCallbacks;
+ private final RebootEscrowKeyStoreManager mKeyStoreManager;
+
interface Callbacks {
boolean isUserSecure(int userId);
@@ -109,11 +123,13 @@
static class Injector {
protected Context mContext;
-
+ private final RebootEscrowKeyStoreManager mKeyStoreManager;
private final RebootEscrowProviderInterface mRebootEscrowProvider;
Injector(Context context) {
mContext = context;
+ mKeyStoreManager = new RebootEscrowKeyStoreManager();
+
RebootEscrowProviderInterface rebootEscrowProvider = null;
// TODO(xunchang) add implementation for server based ror.
if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA,
@@ -138,6 +154,10 @@
return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
}
+ public RebootEscrowKeyStoreManager getKeyStoreManager() {
+ return mKeyStoreManager;
+ }
+
public RebootEscrowProviderInterface getRebootEscrowProvider() {
return mRebootEscrowProvider;
}
@@ -168,6 +188,7 @@
mStorage = storage;
mUserManager = injector.getUserManager();
mEventLog = injector.getEventLog();
+ mKeyStoreManager = injector.getKeyStoreManager();
}
void loadRebootEscrowDataIfAvailable() {
@@ -183,8 +204,12 @@
return;
}
- RebootEscrowKey escrowKey = getAndClearRebootEscrowKey();
- if (escrowKey == null) {
+ // Fetch the key from keystore to decrypt the escrow data & escrow key; this key is
+ // generated before reboot. Note that we will clear the escrow key even if the keystore key
+ // is null.
+ SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey();
+ RebootEscrowKey escrowKey = getAndClearRebootEscrowKey(kk);
+ if (kk == null || escrowKey == null) {
Slog.w(TAG, "Had reboot escrow data for users, but no key; removing escrow storage.");
for (UserInfo user : users) {
mStorage.removeRebootEscrow(user.id);
@@ -197,8 +222,12 @@
boolean allUsersUnlocked = true;
for (UserInfo user : rebootEscrowUsers) {
- allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey);
+ allUsersUnlocked &= restoreRebootEscrowForUser(user.id, escrowKey, kk);
}
+
+ // Clear the old key in keystore. A new key will be generated by new RoR requests.
+ mKeyStoreManager.clearKeyStoreEncryptionKey();
+
onEscrowRestoreComplete(allUsersUnlocked);
}
@@ -212,7 +241,7 @@
}
}
- private RebootEscrowKey getAndClearRebootEscrowKey() {
+ private RebootEscrowKey getAndClearRebootEscrowKey(SecretKey kk) {
RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
if (rebootEscrowProvider == null) {
Slog.w(TAG,
@@ -220,14 +249,16 @@
return null;
}
- RebootEscrowKey key = rebootEscrowProvider.getAndClearRebootEscrowKey(null);
+ // The K_s blob maybe encrypted by K_k as well.
+ RebootEscrowKey key = rebootEscrowProvider.getAndClearRebootEscrowKey(kk);
if (key != null) {
mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK);
}
return key;
}
- private boolean restoreRebootEscrowForUser(@UserIdInt int userId, RebootEscrowKey key) {
+ private boolean restoreRebootEscrowForUser(@UserIdInt int userId, RebootEscrowKey ks,
+ SecretKey kk) {
if (!mStorage.hasRebootEscrow(userId)) {
return false;
}
@@ -236,7 +267,7 @@
byte[] blob = mStorage.readRebootEscrow(userId);
mStorage.removeRebootEscrow(userId);
- RebootEscrowData escrowData = RebootEscrowData.fromEncryptedData(key, blob);
+ RebootEscrowData escrowData = RebootEscrowData.fromEncryptedData(ks, blob, kk);
mCallbacks.onRebootEscrowRestored(escrowData.getSpVersion(),
escrowData.getSyntheticPassword(), userId);
@@ -267,11 +298,16 @@
return;
}
+ SecretKey kk = mKeyStoreManager.generateKeyStoreEncryptionKeyIfNeeded();
+ if (kk == null) {
+ Slog.e(TAG, "Failed to generate encryption key from keystore.");
+ return;
+ }
+
final RebootEscrowData escrowData;
try {
- // TODO(xunchang) further wrap the escrowData with a key from keystore.
escrowData = RebootEscrowData.fromSyntheticPassword(escrowKey, spVersion,
- syntheticPassword);
+ syntheticPassword, kk);
} catch (IOException e) {
setRebootEscrowReady(false);
Slog.w(TAG, "Could not escrow reboot data", e);
@@ -348,7 +384,13 @@
return false;
}
- boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, null);
+ // We will use the same key from keystore to encrypt the escrow key and escrow data blob.
+ SecretKey kk = mKeyStoreManager.getKeyStoreEncryptionKey();
+ if (kk == null) {
+ Slog.e(TAG, "Failed to get encryption key from keystore.");
+ return false;
+ }
+ boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, kk);
if (armedRebootEscrow) {
mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM);
mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 1b27ef4..c0381e4 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -109,6 +109,10 @@
private static final int LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout()
+ /* Buffer for delayed delivery of key event */ 50;
private static final int MULTI_TAP_TIMEOUT = ViewConfiguration.getMultiPressTimeout();
+ /**
+ * Copied from Settings.System.MEDIA_BUTTON_RECEIVER
+ */
+ private static final String MEDIA_BUTTON_RECEIVER = "media_button_receiver";
private final Context mContext;
private final SessionManagerImpl mSessionManagerImpl;
@@ -131,7 +135,6 @@
private KeyguardManager mKeyguardManager;
private AudioManager mAudioManager;
- private ContentResolver mContentResolver;
private boolean mHasFeatureLeanback;
// The FullUserRecord of the current users. (i.e. The foreground user that isn't a profile)
@@ -183,7 +186,6 @@
}
}
}, null /* handler */);
- mContentResolver = mContext.getContentResolver();
mHasFeatureLeanback = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
@@ -831,6 +833,7 @@
*/
final class FullUserRecord implements MediaSessionStack.OnMediaButtonSessionChangedListener {
private final int mFullUserId;
+ private final ContentResolver mContentResolver;
private final MediaSessionStack mPriorityStack;
private final HashMap<IBinder, OnMediaKeyEventDispatchedListenerRecord>
mOnMediaKeyEventDispatchedListeners = new HashMap<>();
@@ -848,10 +851,12 @@
FullUserRecord(int fullUserId) {
mFullUserId = fullUserId;
+ mContentResolver = mContext.createContextAsUser(UserHandle.of(mFullUserId), 0)
+ .getContentResolver();
mPriorityStack = new MediaSessionStack(mAudioPlayerStateMonitor, this);
// Restore the remembered media button receiver before the boot.
- String mediaButtonReceiverInfo = Settings.Secure.getStringForUser(mContentResolver,
- Settings.System.MEDIA_BUTTON_RECEIVER, mFullUserId);
+ String mediaButtonReceiverInfo = Settings.Secure.getString(mContentResolver,
+ MEDIA_BUTTON_RECEIVER);
mLastMediaButtonReceiverHolder =
MediaButtonReceiverHolder.unflattenFromString(
mContext, mediaButtonReceiverInfo);
@@ -970,10 +975,9 @@
mLastMediaButtonReceiverHolder = sessionRecord.getMediaButtonReceiver();
String mediaButtonReceiverInfo = (mLastMediaButtonReceiverHolder == null)
? "" : mLastMediaButtonReceiverHolder.flattenToString();
- Settings.Secure.putStringForUser(mContentResolver,
- Settings.System.MEDIA_BUTTON_RECEIVER,
- mediaButtonReceiverInfo,
- mFullUserId);
+ Settings.Secure.putString(mContentResolver,
+ MEDIA_BUTTON_RECEIVER,
+ mediaButtonReceiverInfo);
}
private void pushAddressedPlayerChangedLocked(
diff --git a/services/core/java/com/android/server/media/metrics/OWNERS b/services/core/java/com/android/server/media/metrics/OWNERS
index f8696ef..e9f0a43 100644
--- a/services/core/java/com/android/server/media/metrics/OWNERS
+++ b/services/core/java/com/android/server/media/metrics/OWNERS
@@ -1,3 +1,4 @@
essick@google.com
nchalko@google.com
-shubang@google.com
\ No newline at end of file
+shubang@google.com
+quxiangfang@google.com
diff --git a/services/core/java/com/android/server/media/metrics/PlaybackMetricsManagerService.java b/services/core/java/com/android/server/media/metrics/PlaybackMetricsManagerService.java
index 9c68349..2a3cc90 100644
--- a/services/core/java/com/android/server/media/metrics/PlaybackMetricsManagerService.java
+++ b/services/core/java/com/android/server/media/metrics/PlaybackMetricsManagerService.java
@@ -18,8 +18,14 @@
import android.content.Context;
import android.media.metrics.IPlaybackMetricsManager;
+import android.media.metrics.NetworkEvent;
+import android.media.metrics.PlaybackErrorEvent;
import android.media.metrics.PlaybackMetrics;
+import android.media.metrics.PlaybackStateEvent;
+import android.os.Binder;
import android.util.Base64;
+import android.util.StatsEvent;
+import android.util.StatsLog;
import com.android.server.SystemService;
@@ -50,6 +56,33 @@
private final class BinderService extends IPlaybackMetricsManager.Stub {
@Override
public void reportPlaybackMetrics(String sessionId, PlaybackMetrics metrics, int userId) {
+ StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(320)
+ .writeInt(Binder.getCallingUid())
+ .writeString(sessionId)
+ .writeLong(metrics.getMediaDurationMillis())
+ .writeInt(metrics.getStreamSource())
+ .writeInt(metrics.getStreamType())
+ .writeInt(metrics.getPlaybackType())
+ .writeInt(metrics.getDrmType())
+ .writeInt(metrics.getContentType())
+ .writeString(metrics.getPlayerName())
+ .writeString(metrics.getPlayerVersion())
+ .writeByteArray(new byte[0]) // TODO: write experiments proto
+ .writeInt(metrics.getVideoFramesPlayed())
+ .writeInt(metrics.getVideoFramesDropped())
+ .writeInt(metrics.getAudioUnderrunCount())
+ .writeLong(metrics.getNetworkBytesRead())
+ .writeLong(metrics.getLocalBytesRead())
+ .writeLong(metrics.getNetworkTransferDurationMillis())
+ .usePooledBuffer()
+ .build();
+ StatsLog.write(statsEvent);
+ }
+
+ @Override
+ public void reportPlaybackStateEvent(
+ String sessionId, PlaybackStateEvent event, int userId) {
// TODO: log it to statsd
}
@@ -60,5 +93,32 @@
String id = Base64.encodeToString(byteId, Base64.DEFAULT);
return id;
}
+
+ @Override
+ public void reportPlaybackErrorEvent(
+ String sessionId, PlaybackErrorEvent event, int userId) {
+ StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(323)
+ .writeString(sessionId)
+ .writeString(event.getExceptionStack())
+ .writeInt(event.getErrorCode())
+ .writeInt(event.getSubErrorCode())
+ .writeLong(event.getTimeSincePlaybackCreatedMillis())
+ .usePooledBuffer()
+ .build();
+ StatsLog.write(statsEvent);
+ }
+
+ public void reportNetworkEvent(
+ String sessionId, NetworkEvent event, int userId) {
+ StatsEvent statsEvent = StatsEvent.newBuilder()
+ .setAtomId(321)
+ .writeString(sessionId)
+ .writeInt(event.getType())
+ .writeLong(event.getTimeSincePlaybackCreatedMillis())
+ .usePooledBuffer()
+ .build();
+ StatsLog.write(statsEvent);
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/CountdownConditionProvider.java b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
index c165fc1..d04aac2 100644
--- a/services/core/java/com/android/server/notification/CountdownConditionProvider.java
+++ b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
@@ -118,7 +118,7 @@
.putExtra(EXTRA_CONDITION_ID, conditionId)
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, REQUEST_CODE,
- intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
alarms.cancel(pendingIntent);
if (mTime > 0) {
final long now = System.currentTimeMillis();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4ab8279..61b218c 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -128,6 +128,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AutomaticZenRule;
+import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.ITransientNotification;
@@ -154,6 +155,7 @@
import android.companion.ICompanionDeviceManager;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.LoggingOnly;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -250,6 +252,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.compat.IPlatformCompat;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
@@ -446,6 +449,17 @@
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
private static final long NOTIFICATION_TRAMPOLINE_BLOCK = 167676448L;
+ /**
+ * Rate limit showing toasts, on a per package basis.
+ *
+ * It limits the number of {@link android.widget.Toast#show()} calls to prevent overburdening
+ * the user with too many toasts in a limited time. Any attempt to show more toasts than allowed
+ * in a certain time frame will result in the toast being discarded.
+ */
+ @ChangeId
+ @LoggingOnly
+ private static final long RATE_LIMIT_TOASTS = 174840628L;
+
private IActivityManager mAm;
private ActivityTaskManagerInternal mAtm;
private ActivityManager mActivityManager;
@@ -466,6 +480,7 @@
private UriGrantsManagerInternal mUgmInternal;
private RoleObserver mRoleObserver;
private UserManager mUm;
+ private IPlatformCompat mPlatformCompat;
private ShortcutHelper mShortcutHelper;
final IBinder mForegroundToken = new Binder();
@@ -1988,6 +2003,8 @@
mDeviceIdleManager = getContext().getSystemService(DeviceIdleManager.class);
mDpm = dpm;
mUm = userManager;
+ mPlatformCompat = IPlatformCompat.Stub.asInterface(
+ ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
mUiHandler = new Handler(UiThread.get().getLooper());
String[] extractorNames;
@@ -5944,7 +5961,9 @@
PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
if (pendingIntent != null) {
am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),
- ALLOWLIST_TOKEN, duration);
+ ALLOWLIST_TOKEN, duration,
+ BroadcastOptions.TEMPORARY_WHITELIST_TYPE_FOREGROUND_SERVICE_ALLOWED
+ );
am.setPendingIntentAllowBgActivityStarts(pendingIntent.getTarget(),
ALLOWLIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER
| FLAG_SERVICE_SENDER));
@@ -6062,7 +6081,6 @@
if (!isAppForeground && metadata != null) {
int flags = metadata.getFlags();
flags &= ~Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE;
- flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
metadata.setFlags(flags);
}
}
@@ -7412,6 +7430,7 @@
private boolean tryShowToast(ToastRecord record, boolean rateLimitingEnabled,
boolean isWithinQuota) {
if (rateLimitingEnabled && !isWithinQuota) {
+ reportCompatRateLimitingToastsChange(record.uid);
Slog.w(TAG, "Package " + record.pkg + " is above allowed toast quota, the "
+ "following toast was blocked and discarded: " + record);
return false;
@@ -7424,6 +7443,19 @@
return record.show();
}
+ /** Reports rate limiting toasts compat change (used when the toast was blocked). */
+ private void reportCompatRateLimitingToastsChange(int uid) {
+ final long id = Binder.clearCallingIdentity();
+ try {
+ mPlatformCompat.reportChangeByUid(RATE_LIMIT_TOASTS, uid);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unexpected exception while reporting toast was blocked due to rate"
+ + " limiting", e);
+ } finally {
+ Binder.restoreCallingIdentity(id);
+ }
+ }
+
@GuardedBy("mToastQueue")
void cancelToastLocked(int index) {
ToastRecord record = mToastQueue.get(index);
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index 78c60d5..7112ae1 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -527,14 +527,14 @@
final PendingIntent pi;
if ("broadcast".equals(intentKind)) {
pi = PendingIntent.getBroadcastAsUser(
- context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT,
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED,
UserHandle.CURRENT);
} else if ("service".equals(intentKind)) {
pi = PendingIntent.getService(
- context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
} else {
pi = PendingIntent.getActivityAsUser(
- context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, null,
+ context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED, null,
UserHandle.CURRENT);
}
builder.setContentIntent(pi);
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 2a9322d..d7a1ba2 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -29,8 +29,6 @@
import static android.os.Trace.traceBegin;
import static android.os.Trace.traceEnd;
-import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -51,7 +49,6 @@
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
-import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -68,6 +65,7 @@
import com.android.internal.content.om.OverlayConfig;
import com.android.server.FgThread;
+import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
@@ -91,7 +89,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.function.Consumer;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Service to manage asset overlays.
@@ -240,9 +238,7 @@
private final OverlayActorEnforcer mActorEnforcer;
- private final Consumer<PackageAndUser> mOnOverlaysChanged = (pair) -> {
- onOverlaysChanged(pair.packageName, pair.userId);
- };
+ private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
public OverlayManagerService(@NonNull final Context context) {
super(context);
@@ -255,19 +251,17 @@
IdmapManager im = new IdmapManager(IdmapDaemon.getInstance(), mPackageManager);
mSettings = new OverlayManagerSettings();
mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
- OverlayConfig.getSystemInstance(), getDefaultOverlayPackages());
+ OverlayConfig.getSystemInstance(), getDefaultOverlayPackages(),
+ new OverlayChangeListener());
mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
- HandlerThread packageReceiverThread = new HandlerThread(TAG);
- packageReceiverThread.start();
-
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(ACTION_PACKAGE_ADDED);
packageFilter.addAction(ACTION_PACKAGE_CHANGED);
packageFilter.addAction(ACTION_PACKAGE_REMOVED);
packageFilter.addDataScheme("package");
getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
- packageFilter, null, packageReceiverThread.getThreadHandler());
+ packageFilter, null, null);
final IntentFilter userFilter = new IntentFilter();
userFilter.addAction(ACTION_USER_ADDED);
@@ -324,7 +318,7 @@
final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
updateAssets(newUserId, targets);
}
- persistSettings();
+ schedulePersistSettings();
} finally {
traceEnd(TRACE_TAG_RRO);
}
@@ -408,17 +402,10 @@
false);
if (pi != null && !pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
-
- try {
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageAdded(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- } else {
- mImpl.onTargetPackageAdded(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- }
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageAdded internal error", e);
+ if (pi.isOverlayPackage()) {
+ mImpl.onOverlayPackageAdded(packageName, userId);
+ } else {
+ mImpl.onTargetPackageAdded(packageName, userId);
}
}
}
@@ -438,17 +425,10 @@
false);
if (pi != null && pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
-
- try {
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageChanged(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- } else {
- mImpl.onTargetPackageChanged(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- }
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageChanged internal error", e);
+ if (pi.isOverlayPackage()) {
+ mImpl.onOverlayPackageChanged(packageName, userId);
+ } else {
+ mImpl.onTargetPackageChanged(packageName, userId);
}
}
}
@@ -467,12 +447,7 @@
mPackageManager.forgetPackageInfo(packageName, userId);
final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
if (oi != null) {
- try {
- mImpl.onOverlayPackageReplacing(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageReplacing internal error", e);
- }
+ mImpl.onOverlayPackageReplacing(packageName, userId);
}
}
}
@@ -491,16 +466,10 @@
false);
if (pi != null && !pi.applicationInfo.isInstantApp()) {
mPackageManager.cachePackageInfo(packageName, userId, pi);
- try {
- if (pi.isOverlayPackage()) {
- mImpl.onOverlayPackageReplaced(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- } else {
- mImpl.onTargetPackageReplaced(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- }
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageReplaced internal error", e);
+ if (pi.isOverlayPackage()) {
+ mImpl.onOverlayPackageReplaced(packageName, userId);
+ } else {
+ mImpl.onTargetPackageReplaced(packageName, userId);
}
}
}
@@ -518,17 +487,10 @@
synchronized (mLock) {
mPackageManager.forgetPackageInfo(packageName, userId);
final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
-
- try {
- if (oi != null) {
- mImpl.onOverlayPackageRemoved(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- } else {
- mImpl.onTargetPackageRemoved(packageName, userId)
- .ifPresent(mOnOverlaysChanged);
- }
- } catch (OperationFailedException e) {
- Slog.e(TAG, "onPackageRemoved internal error", e);
+ if (oi != null) {
+ mImpl.onOverlayPackageRemoved(packageName, userId);
+ } else {
+ mImpl.onTargetPackageRemoved(packageName, userId);
}
}
}
@@ -646,13 +608,7 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- try {
- mImpl.setEnabled(packageName, enable, realUserId)
- .ifPresent(mOnOverlaysChanged);
- return true;
- } catch (OperationFailedException e) {
- return false;
- }
+ return mImpl.setEnabled(packageName, enable, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -677,14 +633,8 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- try {
- mImpl.setEnabledExclusive(packageName,
- false /* withinCategory */, realUserId)
- .ifPresent(mOnOverlaysChanged);
- return true;
- } catch (OperationFailedException e) {
- return false;
- }
+ return mImpl.setEnabledExclusive(packageName, false /* withinCategory */,
+ realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -710,14 +660,8 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- try {
- mImpl.setEnabledExclusive(packageName,
- true /* withinCategory */, realUserId)
- .ifPresent(mOnOverlaysChanged);
- return true;
- } catch (OperationFailedException e) {
- return false;
- }
+ return mImpl.setEnabledExclusive(packageName, true /* withinCategory */,
+ realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -743,13 +687,7 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- try {
- mImpl.setPriority(packageName, parentPackageName, realUserId)
- .ifPresent(mOnOverlaysChanged);
- return true;
- } catch (OperationFailedException e) {
- return false;
- }
+ return mImpl.setPriority(packageName, parentPackageName, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -773,13 +711,7 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- try {
- mImpl.setHighestPriority(packageName, realUserId)
- .ifPresent(mOnOverlaysChanged);
- return true;
- } catch (OperationFailedException e) {
- return false;
- }
+ return mImpl.setHighestPriority(packageName, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -803,13 +735,7 @@
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- try {
- mImpl.setLowestPriority(packageName, realUserId)
- .ifPresent(mOnOverlaysChanged);
- return true;
- } catch (OperationFailedException e) {
- return false;
- }
+ return mImpl.setLowestPriority(packageName, realUserId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -978,27 +904,31 @@
}
};
- private void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
- persistSettings();
- FgThread.getHandler().post(() -> {
- updateAssets(userId, targetPackageName);
+ private final class OverlayChangeListener
+ implements OverlayManagerServiceImpl.OverlayChangeListener {
+ @Override
+ public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
+ schedulePersistSettings();
+ FgThread.getHandler().post(() -> {
+ updateAssets(userId, targetPackageName);
- final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
- Uri.fromParts("package", targetPackageName, null));
- intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ final Intent intent = new Intent(ACTION_OVERLAY_CHANGED,
+ Uri.fromParts("package", targetPackageName, null));
+ intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- if (DEBUG) {
- Slog.d(TAG, "send broadcast " + intent);
- }
+ if (DEBUG) {
+ Slog.d(TAG, "send broadcast " + intent);
+ }
- try {
- ActivityManager.getService().broadcastIntent(null, intent, null, null, 0,
- null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
- userId);
- } catch (RemoteException e) {
- // Intentionally left empty.
- }
- });
+ try {
+ ActivityManager.getService().broadcastIntentWithFeature(null, null, intent,
+ null, null, 0, null, null, null, android.app.AppOpsManager.OP_NONE,
+ null, false, false, userId);
+ } catch (RemoteException e) {
+ // Intentionally left empty.
+ }
+ });
+ }
}
/**
@@ -1071,21 +1001,27 @@
}
}
- private void persistSettings() {
- if (DEBUG) {
- Slog.d(TAG, "Writing overlay settings");
+ private void schedulePersistSettings() {
+ if (mPersistSettingsScheduled.getAndSet(true)) {
+ return;
}
- synchronized (mLock) {
- FileOutputStream stream = null;
- try {
- stream = mSettingsFile.startWrite();
- mSettings.persist(stream);
- mSettingsFile.finishWrite(stream);
- } catch (IOException | XmlPullParserException e) {
- mSettingsFile.failWrite(stream);
- Slog.e(TAG, "failed to persist overlay state", e);
+ IoThread.getHandler().post(() -> {
+ mPersistSettingsScheduled.set(false);
+ if (DEBUG) {
+ Slog.d(TAG, "Writing overlay settings");
}
- }
+ synchronized (mLock) {
+ FileOutputStream stream = null;
+ try {
+ stream = mSettingsFile.startWrite();
+ mSettings.persist(stream);
+ mSettingsFile.finishWrite(stream);
+ } catch (IOException | XmlPullParserException e) {
+ mSettingsFile.failWrite(stream);
+ Slog.e(TAG, "failed to persist overlay state", e);
+ }
+ }
+ });
}
private void restoreSettings() {
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index e60411bb..05a4a38 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -45,7 +45,6 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
/**
@@ -72,6 +71,7 @@
private final OverlayManagerSettings mSettings;
private final OverlayConfig mOverlayConfig;
private final String[] mDefaultOverlays;
+ private final OverlayChangeListener mListener;
/**
* Helper method to merge the overlay manager's (as read from overlays.xml)
@@ -114,12 +114,14 @@
@NonNull final IdmapManager idmapManager,
@NonNull final OverlayManagerSettings settings,
@NonNull final OverlayConfig overlayConfig,
- @NonNull final String[] defaultOverlays) {
+ @NonNull final String[] defaultOverlays,
+ @NonNull final OverlayChangeListener listener) {
mPackageManager = packageManager;
mIdmapManager = idmapManager;
mSettings = settings;
mOverlayConfig = overlayConfig;
mDefaultOverlays = defaultOverlays;
+ mListener = listener;
}
/**
@@ -257,58 +259,52 @@
mSettings.removeUser(userId);
}
- Optional<PackageAndUser> onTargetPackageAdded(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onTargetPackageAdded(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
}
- return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
- Optional<PackageAndUser> onTargetPackageChanged(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
}
- return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
- Optional<PackageAndUser> onTargetPackageReplacing(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onTargetPackageReplacing(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageReplacing packageName=" + packageName + " userId="
+ userId);
}
- return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
- Optional<PackageAndUser> onTargetPackageReplaced(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onTargetPackageReplaced(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageReplaced packageName=" + packageName + " userId=" + userId);
}
- return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
- Optional<PackageAndUser> onTargetPackageRemoved(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
}
- return updateAndRefreshOverlaysForTarget(packageName, userId, 0);
+ updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
/**
* Update the state of any overlays for this target.
*/
- private Optional<PackageAndUser> updateAndRefreshOverlaysForTarget(
- @NonNull final String targetPackageName, final int userId, final int flags)
- throws OperationFailedException {
+ private void updateAndRefreshOverlaysForTarget(@NonNull final String targetPackageName,
+ final int userId, final int flags) {
final List<OverlayInfo> targetOverlays = mSettings.getOverlaysForTarget(targetPackageName,
userId);
@@ -368,13 +364,11 @@
}
if (modified) {
- return Optional.of(new PackageAndUser(targetPackageName, userId));
+ mListener.onOverlaysChanged(targetPackageName, userId);
}
- return Optional.empty();
}
- Optional<PackageAndUser> onOverlayPackageAdded(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId);
}
@@ -382,7 +376,8 @@
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
Slog.w(TAG, "overlay package " + packageName + " was added, but couldn't be found");
- return onOverlayPackageRemoved(packageName, userId);
+ onOverlayPackageRemoved(packageName, userId);
+ return;
}
mSettings.init(packageName, userId, overlayPackage.overlayTarget,
@@ -394,17 +389,15 @@
overlayPackage.overlayCategory);
try {
if (updateState(overlayPackage.overlayTarget, packageName, userId, 0)) {
- return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId));
+ mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
}
- return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
+ Slog.e(TAG, "failed to update settings", e);
mSettings.remove(packageName, userId);
- throw new OperationFailedException("failed to update settings", e);
}
}
- Optional<PackageAndUser> onOverlayPackageChanged(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onOverlayPackageChanged(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onOverlayPackageChanged packageName=" + packageName + " userId=" + userId);
}
@@ -412,16 +405,14 @@
try {
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
if (updateState(oi.targetPackageName, packageName, userId, 0)) {
- return Optional.of(new PackageAndUser(oi.targetPackageName, userId));
+ mListener.onOverlaysChanged(oi.targetPackageName, userId);
}
- return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- throw new OperationFailedException("failed to update settings", e);
+ Slog.e(TAG, "failed to update settings", e);
}
}
- Optional<PackageAndUser> onOverlayPackageReplacing(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onOverlayPackageReplacing(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onOverlayPackageReplacing packageName=" + packageName + " userId="
+ userId);
@@ -432,16 +423,14 @@
if (updateState(oi.targetPackageName, packageName, userId,
FLAG_OVERLAY_IS_BEING_REPLACED)) {
removeIdmapIfPossible(oi);
- return Optional.of(new PackageAndUser(oi.targetPackageName, userId));
+ mListener.onOverlaysChanged(oi.targetPackageName, userId);
}
- return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- throw new OperationFailedException("failed to update settings", e);
+ Slog.e(TAG, "failed to update settings", e);
}
}
- Optional<PackageAndUser> onOverlayPackageReplaced(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onOverlayPackageReplaced(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onOverlayPackageReplaced packageName=" + packageName + " userId="
+ userId);
@@ -450,12 +439,16 @@
final PackageInfo pkg = mPackageManager.getPackageInfo(packageName, userId);
if (pkg == null) {
Slog.w(TAG, "overlay package " + packageName + " was replaced, but couldn't be found");
- return onOverlayPackageRemoved(packageName, userId);
+ onOverlayPackageRemoved(packageName, userId);
+ return;
}
try {
final OverlayInfo oldOi = mSettings.getOverlayInfo(packageName, userId);
if (mustReinitializeOverlay(pkg, oldOi)) {
+ if (oldOi != null && !oldOi.targetPackageName.equals(pkg.overlayTarget)) {
+ mListener.onOverlaysChanged(pkg.overlayTarget, userId);
+ }
mSettings.init(packageName, userId, pkg.overlayTarget, pkg.targetOverlayableName,
pkg.applicationInfo.getBaseCodePath(),
isPackageConfiguredMutable(pkg.packageName),
@@ -464,25 +457,22 @@
}
if (updateState(pkg.overlayTarget, packageName, userId, 0)) {
- return Optional.of(new PackageAndUser(pkg.overlayTarget, userId));
+ mListener.onOverlaysChanged(pkg.overlayTarget, userId);
}
- return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- throw new OperationFailedException("failed to update settings", e);
+ Slog.e(TAG, "failed to update settings", e);
}
}
- Optional<PackageAndUser> onOverlayPackageRemoved(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) {
try {
final OverlayInfo overlayInfo = mSettings.getOverlayInfo(packageName, userId);
if (mSettings.remove(packageName, userId)) {
removeIdmapIfPossible(overlayInfo);
- return Optional.of(new PackageAndUser(overlayInfo.targetPackageName, userId));
+ mListener.onOverlaysChanged(overlayInfo.targetPackageName, userId);
}
- return Optional.empty();
} catch (OverlayManagerSettings.BadKeyException e) {
- throw new OperationFailedException("failed to remove overlay", e);
+ Slog.e(TAG, "failed to remove overlay", e);
}
}
@@ -503,8 +493,8 @@
return mSettings.getOverlaysForUser(userId);
}
- Optional<PackageAndUser> setEnabled(@NonNull final String packageName, final boolean enable,
- final int userId) throws OperationFailedException {
+ boolean setEnabled(@NonNull final String packageName, final boolean enable,
+ final int userId) {
if (DEBUG) {
Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
packageName, enable, userId));
@@ -512,33 +502,30 @@
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- throw new OperationFailedException(
- String.format("failed to find overlay package %s for user %d",
- packageName, userId));
+ return false;
}
try {
final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
if (!oi.isMutable) {
// Ignore immutable overlays.
- throw new OperationFailedException(
- "cannot enable immutable overlay packages in runtime");
+ return false;
}
boolean modified = mSettings.setEnabled(packageName, userId, enable);
modified |= updateState(oi.targetPackageName, oi.packageName, userId, 0);
if (modified) {
- return Optional.of(new PackageAndUser(oi.targetPackageName, userId));
+ mListener.onOverlaysChanged(oi.targetPackageName, userId);
}
- return Optional.empty();
+ return true;
} catch (OverlayManagerSettings.BadKeyException e) {
- throw new OperationFailedException("failed to update settings", e);
+ return false;
}
}
- Optional<PackageAndUser> setEnabledExclusive(@NonNull final String packageName,
- boolean withinCategory, final int userId) throws OperationFailedException {
+ boolean setEnabledExclusive(@NonNull final String packageName, boolean withinCategory,
+ final int userId) {
if (DEBUG) {
Slog.d(TAG, String.format("setEnabledExclusive packageName=%s"
+ " withinCategory=%s userId=%d", packageName, withinCategory, userId));
@@ -546,8 +533,7 @@
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- throw new OperationFailedException(String.format(
- "failed to find overlay package %s for user %d", packageName, userId));
+ return false;
}
try {
@@ -590,11 +576,11 @@
modified |= updateState(targetPackageName, packageName, userId, 0);
if (modified) {
- return Optional.of(new PackageAndUser(targetPackageName, userId));
+ mListener.onOverlaysChanged(targetPackageName, userId);
}
- return Optional.empty();
+ return true;
} catch (OverlayManagerSettings.BadKeyException e) {
- throw new OperationFailedException("failed to update settings", e);
+ return false;
}
}
@@ -610,75 +596,66 @@
return mOverlayConfig.isEnabled(packageName);
}
- Optional<PackageAndUser> setPriority(@NonNull final String packageName,
- @NonNull final String newParentPackageName, final int userId)
- throws OperationFailedException {
+ boolean setPriority(@NonNull final String packageName,
+ @NonNull final String newParentPackageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "setPriority packageName=" + packageName + " newParentPackageName="
+ newParentPackageName + " userId=" + userId);
}
if (!isPackageConfiguredMutable(packageName)) {
- throw new OperationFailedException(String.format(
- "overlay package %s user %d is not updatable", packageName, userId));
+ return false;
}
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- throw new OperationFailedException(String.format(
- "failed to find overlay package %s for user %d", packageName, userId));
+ return false;
}
if (mSettings.setPriority(packageName, newParentPackageName, userId)) {
- return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId));
+ mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
}
- return Optional.empty();
+ return true;
}
- Optional<PackageAndUser> setHighestPriority(@NonNull final String packageName,
- final int userId) throws OperationFailedException {
+ boolean setHighestPriority(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId);
}
if (!isPackageConfiguredMutable(packageName)) {
- throw new OperationFailedException(String.format(
- "overlay package %s user %d is not updatable", packageName, userId));
+ return false;
}
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- throw new OperationFailedException(String.format(
- "failed to find overlay package %s for user %d", packageName, userId));
+ return false;
}
if (mSettings.setHighestPriority(packageName, userId)) {
- return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId));
+ mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
}
- return Optional.empty();
+ return true;
}
- Optional<PackageAndUser> setLowestPriority(@NonNull final String packageName, final int userId)
- throws OperationFailedException {
+ boolean setLowestPriority(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId);
}
if (!isPackageConfiguredMutable(packageName)) {
- throw new OperationFailedException(String.format(
- "overlay package %s user %d is not updatable", packageName, userId));
+ return false;
}
final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
if (overlayPackage == null) {
- throw new OperationFailedException(String.format(
- "failed to find overlay package %s for user %d", packageName, userId));
+ return false;
}
if (mSettings.setLowestPriority(packageName, userId)) {
- return Optional.of(new PackageAndUser(overlayPackage.overlayTarget, userId));
+ mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
}
- return Optional.empty();
+ return true;
}
void dump(@NonNull final PrintWriter pw, @NonNull DumpState dumpState) {
@@ -820,13 +797,12 @@
mIdmapManager.removeIdmap(oi, oi.userId);
}
- static final class OperationFailedException extends Exception {
- OperationFailedException(@NonNull final String message) {
- super(message);
- }
+ interface OverlayChangeListener {
- OperationFailedException(@NonNull final String message, @NonNull Throwable cause) {
- super(message, cause);
- }
+ /**
+ * An event triggered by changes made to overlay state or settings as well as changes that
+ * add or remove target packages of overlays.
+ **/
+ void onOverlaysChanged(@NonNull String targetPackage, int userId);
}
}
diff --git a/services/core/java/com/android/server/om/PackageAndUser.java b/services/core/java/com/android/server/om/PackageAndUser.java
deleted file mode 100644
index 5c38ba7..0000000
--- a/services/core/java/com/android/server/om/PackageAndUser.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.om;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-
-final class PackageAndUser {
- public final @NonNull String packageName;
- public final @UserIdInt int userId;
-
- PackageAndUser(@NonNull String packageName, @UserIdInt int userId) {
- this.packageName = packageName;
- this.userId = userId;
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof PackageAndUser)) {
- return false;
- }
- PackageAndUser other = (PackageAndUser) obj;
- return packageName.equals(other.packageName) && userId == other.userId;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + packageName.hashCode();
- result = prime * result + userId;
- return result;
- }
-
- @Override
- public String toString() {
- return String.format("PackageAndUser{packageName=%s, userId=%d}", packageName, userId);
- }
-}
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index dd507a3..ef0f0ee 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -21,6 +21,7 @@
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.Binder;
import android.os.BugreportParams;
@@ -31,6 +32,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserManager;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.util.Slog;
@@ -53,11 +55,13 @@
private final Object mLock = new Object();
private final Context mContext;
private final AppOpsManager mAppOps;
+ private final TelephonyManager mTelephonyManager;
private final ArraySet<String> mBugreportWhitelistedPackages;
BugreportManagerServiceImpl(Context context) {
mContext = context;
- mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ mAppOps = context.getSystemService(AppOpsManager.class);
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
mBugreportWhitelistedPackages =
SystemConfig.getInstance().getBugreportWhitelistedPackages();
}
@@ -67,11 +71,14 @@
public void startBugreport(int callingUidUnused, String callingPackage,
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
int bugreportMode, IDumpstateListener listener, boolean isScreenshotRequested) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport");
Objects.requireNonNull(callingPackage);
Objects.requireNonNull(bugreportFd);
Objects.requireNonNull(listener);
validateBugreportMode(bugreportMode);
+
+ int callingUid = Binder.getCallingUid();
+ enforcePermission(callingPackage, callingUid, bugreportMode
+ == BugreportParams.BUGREPORT_MODE_TELEPHONY /* checkCarrierPrivileges */);
final long identity = Binder.clearCallingIdentity();
try {
ensureIsPrimaryUser();
@@ -79,13 +86,6 @@
Binder.restoreCallingIdentity(identity);
}
- int callingUid = Binder.getCallingUid();
- mAppOps.checkPackage(callingUid, callingPackage);
-
- if (!mBugreportWhitelistedPackages.contains(callingPackage)) {
- throw new SecurityException(
- callingPackage + " is not whitelisted to use Bugreport API");
- }
synchronized (mLock) {
startBugreportLocked(callingUid, callingPackage, bugreportFd, screenshotFd,
bugreportMode, listener, isScreenshotRequested);
@@ -93,10 +93,11 @@
}
@Override
- @RequiresPermission(android.Manifest.permission.DUMP)
- public void cancelBugreport() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
- "cancelBugreport");
+ @RequiresPermission(android.Manifest.permission.DUMP) // or carrier privileges
+ public void cancelBugreport(int callingUidUnused, String callingPackage) {
+ int callingUid = Binder.getCallingUid();
+ enforcePermission(callingPackage, callingUid, true /* checkCarrierPrivileges */);
+
synchronized (mLock) {
IDumpstate ds = getDumpstateBinderServiceLocked();
if (ds == null) {
@@ -104,7 +105,11 @@
return;
}
try {
- ds.cancelBugreport();
+ // Note: this may throw SecurityException back out to the caller if they aren't
+ // allowed to cancel the report, in which case we should NOT be setting ctl.stop,
+ // since that would unintentionally kill some other app's bugreport, which we
+ // specifically disallow.
+ ds.cancelBugreport(callingUid, callingPackage);
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException in cancelBugreport", e);
}
@@ -127,6 +132,34 @@
}
}
+ private void enforcePermission(
+ String callingPackage, int callingUid, boolean checkCarrierPrivileges) {
+ mAppOps.checkPackage(callingUid, callingPackage);
+
+ // To gain access through the DUMP permission, the OEM has to allow this package explicitly
+ // via sysconfig and privileged permissions.
+ if (mBugreportWhitelistedPackages.contains(callingPackage)
+ && mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ // For carrier privileges, this can include user-installed apps. This is essentially a
+ // function of the current active SIM(s) in the device to let carrier apps through.
+ if (checkCarrierPrivileges
+ && mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
+ == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ return;
+ }
+
+ String message =
+ callingPackage
+ + " does not hold the DUMP permission or is not bugreport-whitelisted "
+ + (checkCarrierPrivileges ? "and does not have carrier privileges " : "")
+ + "to request a bugreport";
+ Slog.w(TAG, message);
+ throw new SecurityException(message);
+ }
+
/**
* Validates that the current user is the primary user.
*
@@ -182,7 +215,7 @@
// lifecycle correctly. If we don't subsequent callers will get
// BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS error.
// Note that listener will be notified by the death recipient below.
- cancelBugreport();
+ cancelBugreport(callingUid, callingPackage);
}
}
diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java
index 7e8ff94..08739cb 100644
--- a/services/core/java/com/android/server/pm/ApkChecksums.java
+++ b/services/core/java/com/android/server/pm/ApkChecksums.java
@@ -36,12 +36,14 @@
import android.content.IntentSender;
import android.content.pm.ApkChecksum;
import android.content.pm.Checksum;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.Signature;
import android.os.Handler;
import android.os.SystemClock;
import android.os.incremental.IncrementalManager;
import android.os.incremental.IncrementalStorage;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
@@ -57,6 +59,7 @@
import android.util.apk.VerityBuilder;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.security.VerityUtils;
import java.io.BufferedInputStream;
@@ -121,12 +124,15 @@
private final Producer<Context> mContext;
private final Producer<Handler> mHandlerProducer;
private final Producer<IncrementalManager> mIncrementalManagerProducer;
+ private final Producer<PackageManagerInternal> mPackageManagerInternalProducer;
Injector(Producer<Context> context, Producer<Handler> handlerProducer,
- Producer<IncrementalManager> incrementalManagerProducer) {
+ Producer<IncrementalManager> incrementalManagerProducer,
+ Producer<PackageManagerInternal> packageManagerInternalProducer) {
mContext = context;
mHandlerProducer = handlerProducer;
mIncrementalManagerProducer = incrementalManagerProducer;
+ mPackageManagerInternalProducer = packageManagerInternalProducer;
}
public Context getContext() {
@@ -140,6 +146,10 @@
public IncrementalManager getIncrementalManager() {
return mIncrementalManagerProducer.produce();
}
+
+ public PackageManagerInternal getPackageManagerInternal() {
+ return mPackageManagerInternalProducer.produce();
+ }
}
/**
@@ -169,104 +179,56 @@
/**
* Serialize checksums to the stream in binary format.
*/
- public static void writeChecksums(OutputStream os, ApkChecksum[] checksums)
+ public static void writeChecksums(OutputStream os, Checksum[] checksums)
throws IOException, CertificateException {
try (DataOutputStream dos = new DataOutputStream(os)) {
dos.writeInt(checksums.length);
- for (ApkChecksum checksum : checksums) {
- final String splitName = checksum.getSplitName();
- if (splitName == null) {
- dos.writeInt(-1);
- } else {
- dos.writeInt(splitName.length());
- dos.writeUTF(splitName);
- }
-
+ for (Checksum checksum : checksums) {
dos.writeInt(checksum.getType());
final byte[] valueBytes = checksum.getValue();
dos.writeInt(valueBytes.length);
dos.write(valueBytes);
-
- final String packageName = checksum.getInstallerPackageName();
- if (packageName == null) {
- dos.writeInt(-1);
- } else {
- dos.writeInt(packageName.length());
- dos.writeUTF(packageName);
- }
-
- final Certificate cert = checksum.getInstallerCertificate();
- final byte[] certBytes = (cert == null) ? null : cert.getEncoded();
- if (certBytes == null) {
- dos.writeInt(-1);
- } else {
- dos.writeInt(certBytes.length);
- dos.write(certBytes);
- }
}
}
}
/**
* Deserialize array of checksums previously stored in
- * {@link #writeChecksums(File, ApkChecksum[])}.
+ * {@link #writeChecksums(OutputStream, Checksum[])}.
*/
- private static ApkChecksum[] readChecksums(File file) throws IOException {
+ private static Checksum[] readChecksums(File file) throws IOException {
try (InputStream is = new FileInputStream(file);
DataInputStream dis = new DataInputStream(is)) {
final int size = dis.readInt();
- ApkChecksum[] checksums = new ApkChecksum[size];
+ Checksum[] checksums = new Checksum[size];
for (int i = 0; i < size; ++i) {
- final String splitName;
- if (dis.readInt() < 0) {
- splitName = null;
- } else {
- splitName = dis.readUTF();
- }
-
final int type = dis.readInt();
final byte[] valueBytes = new byte[dis.readInt()];
dis.read(valueBytes);
-
- final String packageName;
- if (dis.readInt() < 0) {
- packageName = null;
- } else {
- packageName = dis.readUTF();
- }
-
- final byte[] certBytes;
- final int certBytesLength = dis.readInt();
- if (certBytesLength < 0) {
- certBytes = null;
- } else {
- certBytes = new byte[certBytesLength];
- dis.read(certBytes);
- }
- checksums[i] = new ApkChecksum(splitName, new Checksum(type, valueBytes),
- packageName, certBytes);
+ checksums[i] = new Checksum(type, valueBytes);
}
return checksums;
}
}
-
/**
* Fetch or calculate checksums for the collection of files.
*
- * @param filesToChecksum split name, null for base and File to fetch checksums for
- * @param optional mask to fetch readily available checksums
- * @param required mask to forcefully calculate if not available
- * @param trustedInstallers array of certificate to trust, two specific cases:
- * null - trust anybody,
- * [] - trust nobody.
- * @param statusReceiver to receive the resulting checksums
+ * @param filesToChecksum split name, null for base and File to fetch checksums for
+ * @param optional mask to fetch readily available checksums
+ * @param required mask to forcefully calculate if not available
+ * @param installerPackageName package name of the installer of the packages
+ * @param trustedInstallers array of certificate to trust, two specific cases:
+ * null - trust anybody,
+ * [] - trust nobody.
+ * @param statusReceiver to receive the resulting checksums
*/
public static void getChecksums(List<Pair<String, File>> filesToChecksum,
@Checksum.Type int optional,
@Checksum.Type int required,
+ @Nullable String installerPackageName,
@Nullable Certificate[] trustedInstallers,
@NonNull IntentSender statusReceiver,
@NonNull Injector injector) {
@@ -278,8 +240,8 @@
result.add(checksums);
try {
- getAvailableApkChecksums(split, file, optional | required, trustedInstallers,
- checksums);
+ getAvailableApkChecksums(split, file, optional | required, installerPackageName,
+ trustedInstallers, checksums, injector);
} catch (Throwable e) {
Slog.e(TAG, "Preferred checksum calculation error", e);
}
@@ -337,18 +299,21 @@
/**
* Fetch readily available checksums - enforced by kernel or provided by Installer.
*
- * @param split split name, null for base
- * @param file to fetch checksums for
- * @param types mask to fetch checksums
- * @param trustedInstallers array of certificate to trust, two specific cases:
- * null - trust anybody,
- * [] - trust nobody.
- * @param checksums resulting checksums
+ * @param split split name, null for base
+ * @param file to fetch checksums for
+ * @param types mask to fetch checksums
+ * @param installerPackageName package name of the installer of the packages
+ * @param trustedInstallers array of certificate to trust, two specific cases:
+ * null - trust anybody,
+ * [] - trust nobody.
+ * @param checksums resulting checksums
*/
private static void getAvailableApkChecksums(String split, File file,
@Checksum.Type int types,
+ @Nullable String installerPackageName,
@Nullable Certificate[] trustedInstallers,
- Map<Integer, ApkChecksum> checksums) {
+ Map<Integer, ApkChecksum> checksums,
+ @NonNull Injector injector) {
final String filePath = file.getAbsolutePath();
// Always available: FSI or IncFs.
@@ -370,24 +335,72 @@
}
}
- if (trustedInstallers == null || trustedInstallers.length > 0) {
- final File digestsFile = new File(buildDigestsPathForApk(filePath));
- if (digestsFile.exists()) {
- try {
- final ApkChecksum[] digests = readChecksums(digestsFile);
- final Set<Signature> trusted = convertToSet(trustedInstallers);
- for (ApkChecksum digest : digests) {
- if (isRequired(digest.getType(), types, checksums) && isTrusted(digest,
- trusted)) {
- checksums.put(digest.getType(), digest);
- }
- }
- } catch (IOException e) {
- Slog.e(TAG, "Error reading .digests", e);
- } catch (CertificateEncodingException e) {
- Slog.e(TAG, "Error encoding trustedInstallers", e);
+ getInstallerChecksums(split, file, types, installerPackageName, trustedInstallers,
+ checksums, injector);
+ }
+
+ private static void getInstallerChecksums(String split, File file,
+ @Checksum.Type int types,
+ @Nullable String installerPackageName,
+ @Nullable Certificate[] trustedInstallers,
+ Map<Integer, ApkChecksum> checksums,
+ @NonNull Injector injector) {
+ if (TextUtils.isEmpty(installerPackageName)) {
+ return;
+ }
+ if (trustedInstallers != null && trustedInstallers.length == 0) {
+ return;
+ }
+
+ final File digestsFile = new File(buildDigestsPathForApk(file.getAbsolutePath()));
+ if (!digestsFile.exists()) {
+ return;
+ }
+
+ final AndroidPackage installer = injector.getPackageManagerInternal().getPackage(
+ installerPackageName);
+ if (installer == null) {
+ Slog.e(TAG, "Installer package not found.");
+ return;
+ }
+
+ // Obtaining array of certificates used for signing the installer package.
+ final Signature[] certs = installer.getSigningDetails().signatures;
+ final Signature[] pastCerts = installer.getSigningDetails().pastSigningCertificates;
+ if (certs == null || certs.length == 0 || certs[0] == null) {
+ Slog.e(TAG, "Can't obtain calling installer package's certificates.");
+ return;
+ }
+ // According to V2/V3 signing schema, the first certificate corresponds to the public key
+ // in the signing block.
+ byte[] trustedCertBytes = certs[0].toByteArray();
+
+ try {
+ final Checksum[] digests = readChecksums(digestsFile);
+ final Set<Signature> trusted = convertToSet(trustedInstallers);
+
+ if (trusted != null && !trusted.isEmpty()) {
+ // Obtaining array of certificates used for signing the installer package.
+ Signature trustedCert = isTrusted(certs, trusted);
+ if (trustedCert == null) {
+ trustedCert = isTrusted(pastCerts, trusted);
+ }
+ if (trustedCert == null) {
+ return;
+ }
+ trustedCertBytes = trustedCert.toByteArray();
+ }
+
+ for (Checksum digest : digests) {
+ if (isRequired(digest.getType(), types, checksums)) {
+ checksums.put(digest.getType(),
+ new ApkChecksum(split, digest, installerPackageName, trustedCertBytes));
}
}
+ } catch (IOException e) {
+ Slog.e(TAG, "Error reading .digests", e);
+ } catch (CertificateEncodingException e) {
+ Slog.e(TAG, "Error encoding trustedInstallers", e);
}
}
@@ -494,12 +507,16 @@
return set;
}
- private static boolean isTrusted(ApkChecksum checksum, Set<Signature> trusted) {
- if (trusted == null) {
- return true;
+ private static Signature isTrusted(Signature[] signatures, Set<Signature> trusted) {
+ if (signatures == null) {
+ return null;
}
- final Signature signature = new Signature(checksum.getInstallerCertificateBytes());
- return trusted.contains(signature);
+ for (Signature signature : signatures) {
+ if (trusted.contains(signature)) {
+ return signature;
+ }
+ }
+ return null;
}
private static ApkChecksum extractHashFromFS(String split, String filePath) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 3d04b56..b65fc73 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -30,7 +30,6 @@
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING;
import static android.content.pm.PackageManager.INSTALL_STAGED;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
-import static android.content.pm.PackageParser.APEX_FILE_EXTENSION;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_WRONLY;
@@ -85,7 +84,6 @@
import android.content.pm.PackageParser.ApkLite;
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.Signature;
import android.content.pm.dex.DexMetadataHelper;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.content.pm.parsing.result.ParseResult;
@@ -245,8 +243,6 @@
private static final String ATTR_SIGNATURE = "signature";
private static final String ATTR_CHECKSUM_KIND = "checksumKind";
private static final String ATTR_CHECKSUM_VALUE = "checksumValue";
- private static final String ATTR_CHECKSUM_PACKAGE = "checksumPackage";
- private static final String ATTR_CHECKSUM_CERTIFICATE = "checksumCertificate";
private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
private static final int[] EMPTY_CHILD_SESSION_ARRAY = EmptyArray.INT;
@@ -254,6 +250,7 @@
private static final ApkChecksum[] EMPTY_FILE_CHECKSUM_ARRAY = {};
private static final String SYSTEM_DATA_LOADER_PACKAGE = "android";
+ private static final String APEX_FILE_EXTENSION = ".apex";
private static final int INCREMENTAL_STORAGE_BLOCKED_TIMEOUT_MS = 2000;
private static final int INCREMENTAL_STORAGE_UNHEALTHY_TIMEOUT_MS = 7000;
@@ -334,8 +331,6 @@
private boolean mCommitted = false;
@GuardedBy("mLock")
private boolean mRelinquished = false;
- @GuardedBy("mLock")
- private boolean mDestroyed = false;
/** Permissions have been accepted by the user (see {@link #setPermissionsResult}) */
@GuardedBy("mLock")
@@ -402,33 +397,8 @@
@GuardedBy("mLock")
private ArraySet<FileEntry> mFiles = new ArraySet<>();
- static class CertifiedChecksum {
- final @NonNull Checksum mChecksum;
- final @NonNull String mPackageName;
- final @NonNull byte[] mCertificate;
-
- CertifiedChecksum(@NonNull Checksum checksum, @NonNull String packageName,
- @NonNull byte[] certificate) {
- mChecksum = checksum;
- mPackageName = packageName;
- mCertificate = certificate;
- }
-
- Checksum getChecksum() {
- return mChecksum;
- }
-
- String getPackageName() {
- return mPackageName;
- }
-
- byte[] getCertificate() {
- return mCertificate;
- }
- }
-
@GuardedBy("mLock")
- private ArrayMap<String, List<CertifiedChecksum>> mChecksums = new ArrayMap<>();
+ private ArrayMap<String, Checksum[]> mChecksums = new ArrayMap<>();
@Nullable
final StagedSession mStagedSession;
@@ -790,8 +760,13 @@
@GuardedBy("mLock")
private boolean mVerityFound;
- @GuardedBy("mLock")
- private boolean mDataLoaderFinished = false;
+ /**
+ * Both flags should be guarded with mLock whenever changes need to be in lockstep.
+ * Ok to check without mLock in case the proper check is done later, e.g. status callbacks
+ * for DataLoaders with deferred processing.
+ */
+ private volatile boolean mDestroyed = false;
+ private volatile boolean mDataLoaderFinished = false;
@GuardedBy("mLock")
private IncrementalFileStorages mIncrementalFileStorages;
@@ -946,7 +921,7 @@
int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
SessionParams params, long createdMillis, long committedMillis,
File stageDir, String stageCid, InstallationFile[] files,
- ArrayMap<String, List<CertifiedChecksum>> checksums,
+ ArrayMap<String, List<Checksum>> checksums,
boolean prepared, boolean committed, boolean destroyed, boolean sealed,
@Nullable int[] childSessionIds, int parentSessionId, boolean isReady,
boolean isFailed, boolean isApplied, int stagedSessionErrorCode,
@@ -992,7 +967,11 @@
}
if (checksums != null) {
- mChecksums.putAll(checksums);
+ for (int i = 0, isize = checksums.size(); i < isize; ++i) {
+ final String fileName = checksums.keyAt(i);
+ final List<Checksum> fileChecksums = checksums.valueAt(i);
+ mChecksums.put(fileName, fileChecksums.toArray(new Checksum[fileChecksums.size()]));
+ }
}
if (!params.isMultiPackage && (stageDir == null) == (stageCid == null)) {
@@ -1290,16 +1269,6 @@
throw new IllegalStateException("Can't obtain calling installer's package.");
}
- // Obtaining array of certificates used for signing the installer package.
- final Signature[] certs = callingInstaller.getSigningDetails().signatures;
- if (certs == null || certs.length == 0 || certs[0] == null) {
- throw new IllegalStateException(
- "Can't obtain calling installer package's certificates.");
- }
- // According to V2/V3 signing schema, the first certificate corresponds to the public key
- // in the signing block.
- final byte[] mainCertificateBytes = certs[0].toByteArray();
-
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
assertPreparedAndNotCommittedOrDestroyedLocked("addChecksums");
@@ -1308,13 +1277,7 @@
throw new IllegalStateException("Duplicate checksums.");
}
- List<CertifiedChecksum> fileChecksums = new ArrayList<>();
- mChecksums.put(name, fileChecksums);
-
- for (Checksum checksum : checksums) {
- fileChecksums.add(new CertifiedChecksum(checksum, initiatingPackageName,
- mainCertificateBytes));
- }
+ mChecksums.put(name, checksums);
}
}
@@ -3069,34 +3032,23 @@
maybeStageFsveritySignatureLocked(dexMetadataFile, targetDexMetadataFile);
}
- private static ApkChecksum[] createApkChecksums(String splitName,
- List<CertifiedChecksum> checksums) {
- ApkChecksum[] result = new ApkChecksum[checksums.size()];
- for (int i = 0, size = checksums.size(); i < size; ++i) {
- CertifiedChecksum checksum = checksums.get(i);
- result[i] = new ApkChecksum(splitName, checksum.getChecksum(),
- checksum.getPackageName(), checksum.getCertificate());
- }
- return result;
- }
-
@GuardedBy("mLock")
private void maybeStageDigestsLocked(File origFile, File targetFile, String splitName)
throws PackageManagerException {
- final List<CertifiedChecksum> checksums = mChecksums.get(origFile.getName());
+ final Checksum[] checksums = mChecksums.get(origFile.getName());
if (checksums == null) {
return;
}
mChecksums.remove(origFile.getName());
- if (checksums.isEmpty()) {
+ if (checksums.length == 0) {
return;
}
final String targetDigestsPath = ApkChecksums.buildDigestsPathForApk(targetFile.getName());
final File targetDigestsFile = new File(stageDir, targetDigestsPath);
try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
- ApkChecksums.writeChecksums(os, createApkChecksums(splitName, checksums));
+ ApkChecksums.writeChecksums(os, checksums);
final byte[] checksumsBytes = os.toByteArray();
if (!isIncrementalInstallation() || mIncrementalFileStorages == null) {
@@ -3613,19 +3565,15 @@
return;
}
- synchronized (mLock) {
- if (mDestroyed || mDataLoaderFinished) {
- // No need to worry about post installation
- return;
- }
+ if (mDestroyed || mDataLoaderFinished) {
+ // No need to worry about post installation
+ return;
}
try {
IDataLoader dataLoader = dataLoaderManager.getDataLoader(dataLoaderId);
if (dataLoader == null) {
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failure to obtain data loader");
return;
@@ -3658,9 +3606,7 @@
break;
}
case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: {
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
if (hasParentSessionId()) {
mSessionProvider.getSession(
getParentSessionId()).dispatchSessionSealed();
@@ -3673,9 +3619,7 @@
break;
}
case IDataLoaderStatusListener.DATA_LOADER_IMAGE_NOT_READY: {
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Failed to prepare image.");
if (manualStartAndDestroy) {
@@ -3694,9 +3638,7 @@
break;
}
case IDataLoaderStatusListener.DATA_LOADER_UNRECOVERABLE:
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"DataLoader reported unrecoverable failure.");
break;
@@ -3734,11 +3676,9 @@
final IStorageHealthListener healthListener = new IStorageHealthListener.Stub() {
@Override
public void onHealthStatus(int storageId, int status) {
- synchronized (mLock) {
- if (mDestroyed || mDataLoaderFinished) {
- // No need to worry about post installation
- return;
- }
+ if (mDestroyed || mDataLoaderFinished) {
+ // No need to worry about post installation
+ return;
}
switch (status) {
@@ -3753,9 +3693,7 @@
// fallthrough
case IStorageHealthListener.HEALTH_STATUS_UNHEALTHY:
// Even ADB installation can't wait for missing pages for too long.
- synchronized (mLock) {
- mDataLoaderFinished = true;
- }
+ mDataLoaderFinished = true;
dispatchSessionValidationFailure(INSTALL_FAILED_MEDIA_UNAVAILABLE,
"Image is missing pages required for installation.");
break;
@@ -4338,18 +4276,13 @@
}
for (int i = 0, isize = mChecksums.size(); i < isize; ++i) {
- String fileName = mChecksums.keyAt(i);
- List<CertifiedChecksum> checksums = mChecksums.valueAt(i);
- for (int j = 0, jsize = checksums.size(); j < jsize; ++j) {
- CertifiedChecksum checksum = checksums.get(j);
+ final String fileName = mChecksums.keyAt(i);
+ final Checksum[] checksums = mChecksums.valueAt(i);
+ for (Checksum checksum : checksums) {
out.startTag(null, TAG_SESSION_CHECKSUM);
writeStringAttribute(out, ATTR_NAME, fileName);
- out.attributeInt(null, ATTR_CHECKSUM_KIND, checksum.getChecksum().getType());
- writeByteArrayAttribute(out, ATTR_CHECKSUM_VALUE,
- checksum.getChecksum().getValue());
- writeStringAttribute(out, ATTR_CHECKSUM_PACKAGE, checksum.getPackageName());
- writeByteArrayAttribute(out, ATTR_CHECKSUM_CERTIFICATE,
- checksum.getCertificate());
+ out.attributeInt(null, ATTR_CHECKSUM_KIND, checksum.getType());
+ writeByteArrayAttribute(out, ATTR_CHECKSUM_VALUE, checksum.getValue());
out.endTag(null, TAG_SESSION_CHECKSUM);
}
}
@@ -4467,7 +4400,7 @@
int autoRevokePermissionsMode = MODE_DEFAULT;
List<Integer> childSessionIds = new ArrayList<>();
List<InstallationFile> files = new ArrayList<>();
- ArrayMap<String, List<CertifiedChecksum>> checksums = new ArrayMap<>();
+ ArrayMap<String, List<Checksum>> checksums = new ArrayMap<>();
int outerDepth = in.getDepth();
int type;
while ((type = in.next()) != XmlPullParser.END_DOCUMENT
@@ -4499,18 +4432,16 @@
}
if (TAG_SESSION_CHECKSUM.equals(in.getName())) {
final String fileName = readStringAttribute(in, ATTR_NAME);
- final CertifiedChecksum certifiedChecksum = new CertifiedChecksum(
- new Checksum(in.getAttributeInt(null, ATTR_CHECKSUM_KIND, 0),
- readByteArrayAttribute(in, ATTR_CHECKSUM_VALUE)),
- readStringAttribute(in, ATTR_CHECKSUM_PACKAGE),
- readByteArrayAttribute(in, ATTR_CHECKSUM_CERTIFICATE));
+ final Checksum checksum = new Checksum(
+ in.getAttributeInt(null, ATTR_CHECKSUM_KIND, 0),
+ readByteArrayAttribute(in, ATTR_CHECKSUM_VALUE));
- List<CertifiedChecksum> certifiedChecksums = checksums.get(fileName);
- if (certifiedChecksums == null) {
- certifiedChecksums = new ArrayList<>();
- checksums.put(fileName, certifiedChecksums);
+ List<Checksum> fileChecksums = checksums.get(fileName);
+ if (fileChecksums == null) {
+ fileChecksums = new ArrayList<>();
+ checksums.put(fileName, fileChecksums);
}
- certifiedChecksums.add(certifiedChecksum);
+ fileChecksums.add(checksum);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4467b51..de7338f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -582,6 +582,52 @@
@Retention(RetentionPolicy.SOURCE)
public @interface ScanFlags {}
+ /**
+ * Used as the result code of the {@link #getPackageStartability}.
+ */
+ @IntDef(value = {
+ PACKAGE_STARTABILITY_OK,
+ PACKAGE_STARTABILITY_NOT_FOUND,
+ PACKAGE_STARTABILITY_NOT_SYSTEM,
+ PACKAGE_STARTABILITY_FROZEN,
+ PACKAGE_STARTABILITY_DIRECT_BOOT_UNSUPPORTED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PackageStartability {}
+
+ /**
+ * Used as the result code of the {@link #getPackageStartability} to indicate
+ * the given package is allowed to start.
+ */
+ static final int PACKAGE_STARTABILITY_OK = 0;
+
+ /**
+ * Used as the result code of the {@link #getPackageStartability} to indicate
+ * the given package is <b>not</b> allowed to start because it's not found
+ * (could be due to that package is invisible to the given user).
+ */
+ static final int PACKAGE_STARTABILITY_NOT_FOUND = 1;
+
+ /**
+ * Used as the result code of the {@link #getPackageStartability} to indicate
+ * the given package is <b>not</b> allowed to start because it's not a system app
+ * and the system is running in safe mode.
+ */
+ static final int PACKAGE_STARTABILITY_NOT_SYSTEM = 2;
+
+ /**
+ * Used as the result code of the {@link #getPackageStartability} to indicate
+ * the given package is <b>not</b> allowed to start because it's currently frozen.
+ */
+ static final int PACKAGE_STARTABILITY_FROZEN = 3;
+
+ /**
+ * Used as the result code of the {@link #getPackageStartability} to indicate
+ * the given package is <b>not</b> allowed to start because it doesn't support
+ * direct boot.
+ */
+ static final int PACKAGE_STARTABILITY_DIRECT_BOOT_UNSUPPORTED = 4;
+
private static final String STATIC_SHARED_LIB_DELIMITER = "_";
/** Extension of the compressed packages */
public final static String COMPRESSED_EXTENSION = ".gz";
@@ -4117,10 +4163,10 @@
final long packedStatus = getDomainVerificationStatusLPr(ps, userId);
final int status = (int) (packedStatus >> 32);
if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS
- || status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
+ || status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
if (DEBUG_INSTANT) {
Slog.v(TAG, "DENY instant app;"
- + " pkg: " + packageName + ", status: " + status);
+ + " pkg: " + packageName + ", status: " + status);
}
return false;
}
@@ -4450,7 +4496,7 @@
}
if (checkShell) {
PackageManagerServiceUtils.enforceShellRestriction(
- mInjector.getUserManagerInternal(),
+ mInjector.getUserManagerInternal(),
UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
}
final int callingUserId = UserHandle.getUserId(callingUid);
@@ -4506,7 +4552,7 @@
}
if (checkShell) {
PackageManagerServiceUtils.enforceShellRestriction(
- mInjector.getUserManagerInternal(),
+ mInjector.getUserManagerInternal(),
UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
}
final int callingUserId = UserHandle.getUserId(callingUid);
@@ -4609,8 +4655,8 @@
}
}
public ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
- Intent intent, int matchFlags, List<ResolveInfo> candidates,
- CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
+ Intent intent, int matchFlags, List<ResolveInfo> candidates,
+ CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
synchronized (mLock) {
return super.filterCandidatesWithDomainPreferredActivitiesLPrBody(intent,
matchFlags, candidates, xpDomainInfo, userId, debug);
@@ -4699,47 +4745,54 @@
private static final boolean SNAPSHOT_ENABLED = true;
/**
- * Return the live or cached computer. The method will rebuild the
- * cached computer if necessary.
+ * Return the live computer.
*/
- private Computer computer(boolean live) {
- if (live || !SNAPSHOT_ENABLED) {
+ private Computer liveComputer() {
+ return mLiveComputer;
+ }
+
+ /**
+ * Return the cached computer. The method will rebuild the cached computer if necessary.
+ * The live computer will be returned if snapshots are disabled.
+ */
+ private Computer snapshotComputer() {
+ if (!SNAPSHOT_ENABLED) {
return mLiveComputer;
- } else {
- int hits = 0;
- if (TRACE_CACHES) {
- hits = mSnapshotHits.incrementAndGet();
- }
- Computer c = mSnapshotComputer;
- if ((sSnapshotInvalid || (c == null)) && !sSnapshotCorked) {
- synchronized (mLock) {
- // Rebuild the computer if it is invalid and if the cache is not
- // corked. The lock is taken inside the rebuild method. Note that
- // the cache might be invalidated as it is rebuilt. However, the
- // cache is still consistent and is current as of the time this
- // function is entered.
- if (sSnapshotInvalid) {
- rebuildSnapshot(hits);
- }
- // Guaranteed to be non-null
- c = mSnapshotComputer;
- }
- }
+ }
+ int hits = 0;
+ if (TRACE_CACHES) {
+ hits = mSnapshotHits.incrementAndGet();
+ }
+ Computer c = mSnapshotComputer;
+ if (sSnapshotCorked && (c != null)) {
+ // Snapshots are corked, which means new ones should not be built right now.
return c;
}
+ if (sSnapshotInvalid || (c == null)) {
+ // The snapshot is invalid if it is marked as invalid or if it is null. If it
+ // is null, then it is currently being rebuilt by rebuildSnapshot().
+ synchronized (mLock) {
+ // Rebuild the snapshot if it is invalid. Note that the snapshot might be
+ // invalidated as it is rebuilt. However, the snapshot is still
+ // self-consistent (the lock is being held)and is current as of the time
+ // this function is entered.
+ if (sSnapshotInvalid) {
+ rebuildSnapshot(hits);
+ }
+
+ // Guaranteed to be non-null. mSnapshotComputer is only be set to null
+ // temporarily in rebuildSnapshot(), which is guarded by mLock(). Since
+ // the mLock is held in this block and since rebuildSnapshot() is
+ // complete, the attribute can not now be null.
+ c = mSnapshotComputer;
+ }
+ }
+ return c;
}
/**
- * Return the live computer if the thread holds the lock, and the cached
- * computer otehrwise. This method is for functions that are unsure
- * which computer to use.
- **/
- private Computer computer() {
- return computer(Thread.holdsLock(mLock));
- }
-
- /**
- * Rebuild the cached computer.
+ * Rebuild the cached computer. mSnapshotComputer is temporarily set to null to block
+ * other threads from using the invalid computer until it is rebuilt.
*/
@GuardedBy("mLock")
private void rebuildSnapshot(int hits) {
@@ -4759,7 +4812,7 @@
/**
* Create a live computer
*/
- private ComputerLocked liveComputer() {
+ private ComputerLocked createLiveComputer() {
return new ComputerLocked(new Snapshot(Snapshot.LIVE));
}
@@ -5584,6 +5637,9 @@
if (applicationInfo == null) {
throw new ParcelableException(new PackageManager.NameNotFoundException(packageName));
}
+ final InstallSourceInfo installSourceInfo = getInstallSourceInfo(packageName);
+ final String installerPackageName =
+ installSourceInfo != null ? installSourceInfo.getInitiatingPackageName() : null;
List<Pair<String, File>> filesToChecksum = new ArrayList<>();
@@ -5605,9 +5661,10 @@
ApkChecksums.Injector injector = new ApkChecksums.Injector(
() -> mContext,
() -> handler,
- () -> mInjector.getIncrementalManager());
- ApkChecksums.getChecksums(filesToChecksum, optional, required, trustedCerts,
- statusReceiver, injector);
+ () -> mInjector.getIncrementalManager(),
+ () -> mPmInternal);
+ ApkChecksums.getChecksums(filesToChecksum, optional, required, installerPackageName,
+ trustedCerts, statusReceiver, injector);
});
}
@@ -6054,7 +6111,7 @@
// corked initially to ensure a cached computer is not built until the end of the
// constructor.
sSnapshotCorked = true;
- mLiveComputer = liveComputer();
+ mLiveComputer = createLiveComputer();
mSnapshotComputer = mLiveComputer;
// Link up the watchers
@@ -6230,7 +6287,7 @@
// corked initially to ensure a cached computer is not built until the end of the
// constructor.
sSnapshotCorked = true;
- mLiveComputer = liveComputer();
+ mLiveComputer = createLiveComputer();
mSnapshotComputer = mLiveComputer;
// CHECKSTYLE:OFF IndentationCheck
@@ -7611,11 +7668,11 @@
* </ol>
*/
private boolean canViewInstantApps(int callingUid, int userId) {
- return computer(true).canViewInstantApps(callingUid, userId);
+ return liveComputer().canViewInstantApps(callingUid, userId);
}
private PackageInfo generatePackageInfo(PackageSetting ps, int flags, int userId) {
- return computer(true).generatePackageInfo(ps, flags, userId);
+ return liveComputer().generatePackageInfo(ps, flags, userId);
}
@Override
@@ -7628,30 +7685,44 @@
throw new SecurityException("User doesn't exist");
}
enforceCrossUserPermission(callingUid, userId, false, false, "checkPackageStartable");
+ switch (getPackageStartability(packageName, callingUid, userId)) {
+ case PACKAGE_STARTABILITY_NOT_FOUND:
+ throw new SecurityException("Package " + packageName + " was not found!");
+ case PACKAGE_STARTABILITY_NOT_SYSTEM:
+ throw new SecurityException("Package " + packageName + " not a system app!");
+ case PACKAGE_STARTABILITY_FROZEN:
+ throw new SecurityException("Package " + packageName + " is currently frozen!");
+ case PACKAGE_STARTABILITY_DIRECT_BOOT_UNSUPPORTED:
+ throw new SecurityException("Package " + packageName + " is not encryption aware!");
+ case PACKAGE_STARTABILITY_OK:
+ default:
+ return;
+ }
+ }
+
+ private @PackageStartability int getPackageStartability(String packageName,
+ int callingUid, int userId) {
final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
synchronized (mLock) {
final PackageSetting ps = mSettings.getPackageLPr(packageName);
- if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)) {
- throw new SecurityException("Package " + packageName + " was not found!");
- }
-
- if (!ps.getInstalled(userId)) {
- throw new SecurityException(
- "Package " + packageName + " was not installed for user " + userId + "!");
+ if (ps == null || shouldFilterApplicationLocked(ps, callingUid, userId)
+ || !ps.getInstalled(userId)) {
+ return PACKAGE_STARTABILITY_NOT_FOUND;
}
if (mSafeMode && !ps.isSystem()) {
- throw new SecurityException("Package " + packageName + " not a system app!");
+ return PACKAGE_STARTABILITY_NOT_SYSTEM;
}
if (mFrozenPackages.contains(packageName)) {
- throw new SecurityException("Package " + packageName + " is currently frozen!");
+ return PACKAGE_STARTABILITY_FROZEN;
}
if (!userKeyUnlocked && !AndroidPackageUtils.isEncryptionAware(ps.pkg)) {
- throw new SecurityException("Package " + packageName + " is not encryption aware!");
+ return PACKAGE_STARTABILITY_DIRECT_BOOT_UNSUPPORTED;
}
}
+ return PACKAGE_STARTABILITY_OK;
}
@Override
@@ -7680,8 +7751,7 @@
@Override
public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
- // SNAPSHOT
- return computer(false).getPackageInfo(packageName, flags, userId);
+ return snapshotComputer().getPackageInfo(packageName, flags, userId);
}
@Override
@@ -7699,23 +7769,23 @@
*/
private PackageInfo getPackageInfoInternal(String packageName, long versionCode,
int flags, int filterCallingUid, int userId) {
- return computer(true).getPackageInfoInternal(packageName, versionCode,
+ return liveComputer().getPackageInfoInternal(packageName, versionCode,
flags, filterCallingUid, userId);
}
private PackageInfo getPackageInfoInternalBody(String packageName, long versionCode,
int flags, int filterCallingUid, int userId) {
- return computer(true).getPackageInfoInternalBody(packageName, versionCode,
+ return liveComputer().getPackageInfoInternalBody(packageName, versionCode,
flags, filterCallingUid, userId);
}
private boolean isComponentVisibleToInstantApp(@Nullable ComponentName component) {
- return computer(true).isComponentVisibleToInstantApp(component);
+ return liveComputer().isComponentVisibleToInstantApp(component);
}
private boolean isComponentVisibleToInstantApp(
@Nullable ComponentName component, @ComponentType int type) {
- return computer(true).isComponentVisibleToInstantApp(
+ return liveComputer().isComponentVisibleToInstantApp(
component, type);
}
@@ -7730,7 +7800,7 @@
@GuardedBy("mLock")
private boolean shouldFilterApplicationLocked(@Nullable PackageSetting ps, int callingUid,
@Nullable ComponentName component, @ComponentType int componentType, int userId) {
- return computer(true).shouldFilterApplicationLocked(ps, callingUid,
+ return liveComputer().shouldFilterApplicationLocked(ps, callingUid,
component, componentType, userId);
}
@@ -7740,14 +7810,14 @@
@GuardedBy("mLock")
private boolean shouldFilterApplicationLocked(
@Nullable PackageSetting ps, int callingUid, int userId) {
- return computer(true).shouldFilterApplicationLocked(
+ return liveComputer().shouldFilterApplicationLocked(
ps, callingUid, userId);
}
@GuardedBy("mLock")
private boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId,
int flags) {
- return computer(true).filterSharedLibPackageLPr(ps, uid, userId,
+ return liveComputer().filterSharedLibPackageLPr(ps, uid, userId,
flags);
}
@@ -7818,7 +7888,7 @@
}
private int getPackageUidInternal(String packageName, int flags, int userId, int callingUid) {
- return computer(true).getPackageUidInternal(packageName, flags, userId, callingUid);
+ return liveComputer().getPackageUidInternal(packageName, flags, userId, callingUid);
}
@Override
@@ -7865,14 +7935,13 @@
@GuardedBy("mLock")
private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
int filterCallingUid, int userId) {
- return computer(true).generateApplicationInfoFromSettingsLPw(packageName, flags,
+ return liveComputer().generateApplicationInfoFromSettingsLPw(packageName, flags,
filterCallingUid, userId);
}
@Override
public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
- // SNAPSHOT
- return computer(false).getApplicationInfo(packageName, flags, userId);
+ return snapshotComputer().getApplicationInfo(packageName, flags, userId);
}
/**
@@ -7883,13 +7952,13 @@
*/
private ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
int filterCallingUid, int userId) {
- return computer(true).getApplicationInfoInternal(packageName, flags,
+ return liveComputer().getApplicationInfoInternal(packageName, flags,
filterCallingUid, userId);
}
private ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags,
int filterCallingUid, int userId) {
- return computer(true).getApplicationInfoInternalBody(packageName, flags,
+ return liveComputer().getApplicationInfoInternalBody(packageName, flags,
filterCallingUid, userId);
}
@@ -8122,28 +8191,28 @@
* Update given flags based on encryption status of current user.
*/
private int updateFlags(int flags, int userId) {
- return computer(true).updateFlags(flags, userId);
+ return liveComputer().updateFlags(flags, userId);
}
/**
* Update given flags when being used to request {@link PackageInfo}.
*/
private int updateFlagsForPackage(int flags, int userId) {
- return computer(true).updateFlagsForPackage(flags, userId);
+ return liveComputer().updateFlagsForPackage(flags, userId);
}
/**
* Update given flags when being used to request {@link ApplicationInfo}.
*/
private int updateFlagsForApplication(int flags, int userId) {
- return computer(true).updateFlagsForApplication(flags, userId);
+ return liveComputer().updateFlagsForApplication(flags, userId);
}
/**
* Update given flags when being used to request {@link ComponentInfo}.
*/
private int updateFlagsForComponent(int flags, int userId) {
- return computer(true).updateFlagsForComponent(flags, userId);
+ return liveComputer().updateFlagsForComponent(flags, userId);
}
/**
@@ -8173,14 +8242,14 @@
*/
private int updateFlagsForResolve(int flags, int userId, int callingUid,
boolean wantInstantApps, boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
- return computer(true).updateFlagsForResolve(flags, userId, callingUid,
+ return liveComputer().updateFlagsForResolve(flags, userId, callingUid,
wantInstantApps, isImplicitImageCaptureIntentAndNotSetByDpc);
}
private int updateFlagsForResolve(int flags, int userId, int callingUid,
boolean wantInstantApps, boolean onlyExposedExplicitly,
boolean isImplicitImageCaptureIntentAndNotSetByDpc) {
- return computer(true).updateFlagsForResolve(flags, userId, callingUid,
+ return liveComputer().updateFlagsForResolve(flags, userId, callingUid,
wantInstantApps, onlyExposedExplicitly,
isImplicitImageCaptureIntentAndNotSetByDpc);
}
@@ -8204,8 +8273,7 @@
@Override
public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
- // SNAPSHOT
- return computer(false).getActivityInfo(component, flags, userId);
+ return snapshotComputer().getActivityInfo(component, flags, userId);
}
/**
@@ -8216,18 +8284,18 @@
*/
private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
int filterCallingUid, int userId) {
- return computer(true).getActivityInfoInternal(component, flags,
+ return liveComputer().getActivityInfoInternal(component, flags,
filterCallingUid, userId);
}
private ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags,
int filterCallingUid, int userId) {
- return computer(true).getActivityInfoInternalBody(component, flags,
+ return liveComputer().getActivityInfoInternalBody(component, flags,
filterCallingUid, userId);
}
private boolean isRecentsAccessingChildProfiles(int callingUid, int targetUserId) {
- return computer(true).isRecentsAccessingChildProfiles(callingUid, targetUserId);
+ return liveComputer().isRecentsAccessingChildProfiles(callingUid, targetUserId);
}
@Override
@@ -8490,13 +8558,12 @@
@Override
public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
- // SNAPSHOT
- return computer(false).getServiceInfo(component, flags, userId);
+ return snapshotComputer().getServiceInfo(component, flags, userId);
}
private ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId,
int callingUid) {
- return computer(true).getServiceInfoBody(component, flags, userId,
+ return liveComputer().getServiceInfoBody(component, flags, userId,
callingUid);
}
@@ -8708,8 +8775,7 @@
// NOTE: Can't remove without a major refactor. Keep around for now.
@Override
public int checkUidPermission(String permName, int uid) {
- // SNAPSHOT
- return computer(false).checkUidPermission(permName, uid);
+ return snapshotComputer().checkUidPermission(permName, uid);
}
@Override
@@ -9024,17 +9090,16 @@
*/
@Override
public String[] getPackagesForUid(int uid) {
- // SNAPSHOT
- return computer(false).getPackagesForUid(uid);
+ return snapshotComputer().getPackagesForUid(uid);
}
private String[] getPackagesForUidInternal(int uid, int callingUid) {
- return computer(true).getPackagesForUidInternal(uid, callingUid);
+ return liveComputer().getPackagesForUidInternal(uid, callingUid);
}
private String[] getPackagesForUidInternalBody(int callingUid, int userId, int appId,
boolean isCallerInstantApp) {
- return computer(true).getPackagesForUidInternalBody(callingUid, userId, appId,
+ return liveComputer().getPackagesForUidInternalBody(callingUid, userId, appId,
isCallerInstantApp);
}
@@ -9323,13 +9388,13 @@
* Returns whether or not instant apps have been disabled remotely.
*/
private boolean areWebInstantAppsDisabled(int userId) {
- return computer(true).areWebInstantAppsDisabled(userId);
+ return liveComputer().areWebInstantAppsDisabled(userId);
}
private boolean isInstantAppResolutionAllowed(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
boolean skipPackageCheck) {
- return computer(true).isInstantAppResolutionAllowed(
+ return liveComputer().isInstantAppResolutionAllowed(
intent, resolvedActivities, userId,
skipPackageCheck);
}
@@ -9339,7 +9404,7 @@
private boolean isInstantAppResolutionAllowedBody(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
boolean skipPackageCheck) {
- return computer(true).isInstantAppResolutionAllowedBody(
+ return liveComputer().isInstantAppResolutionAllowedBody(
intent, resolvedActivities, userId,
skipPackageCheck);
}
@@ -9478,13 +9543,13 @@
@GuardedBy("mLock")
private boolean isImplicitImageCaptureIntentAndNotSetByDpcLocked(Intent intent, int userId,
String resolvedType, int flags) {
- return computer(true).isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId,
+ return liveComputer().isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId,
resolvedType, flags);
}
private boolean isPersistentPreferredActivitySetByDpm(Intent intent, int userId,
String resolvedType, int flags) {
- return computer(true).isPersistentPreferredActivitySetByDpm(intent, userId,
+ return liveComputer().isPersistentPreferredActivitySetByDpm(intent, userId,
resolvedType, flags);
}
@@ -9809,12 +9874,12 @@
}
private UserInfo getProfileParent(int userId) {
- return computer(true).getProfileParent(userId);
+ return liveComputer().getProfileParent(userId);
}
private List<CrossProfileIntentFilter> getMatchingCrossProfileIntentFilters(Intent intent,
String resolvedType, int userId) {
- return computer(true).getMatchingCrossProfileIntentFilters(intent,
+ return liveComputer().getMatchingCrossProfileIntentFilters(intent,
resolvedType, userId);
}
@@ -9836,13 +9901,12 @@
* instant, returns {@code null}.
*/
private String getInstantAppPackageName(int callingUid) {
- // SNAPSHOT
- return computer(false).getInstantAppPackageName(callingUid);
+ return snapshotComputer().getInstantAppPackageName(callingUid);
}
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int userId) {
- return computer(true).queryIntentActivitiesInternal(intent,
+ return liveComputer().queryIntentActivitiesInternal(intent,
resolvedType, flags, userId);
}
@@ -9866,7 +9930,7 @@
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, @PrivateResolveFlags int privateResolveFlags,
int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits) {
- return computer(true).queryIntentActivitiesInternal(intent,
+ return liveComputer().queryIntentActivitiesInternal(intent,
resolvedType, flags, privateResolveFlags,
filterCallingUid, userId, resolveForStart, allowDynamicSplits);
}
@@ -9875,7 +9939,7 @@
Intent intent, String resolvedType, int flags, int filterCallingUid, int userId,
boolean resolveForStart, boolean allowDynamicSplits, String pkgName,
String instantAppPkgName) {
- return computer(true).queryIntentActivitiesInternalBody(
+ return liveComputer().queryIntentActivitiesInternalBody(
intent, resolvedType, flags, filterCallingUid, userId,
resolveForStart, allowDynamicSplits, pkgName,
instantAppPkgName);
@@ -9884,7 +9948,7 @@
private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
String resolvedType, int flags, int userId, boolean resolveForStart,
boolean isRequesterInstantApp) {
- return computer(true).maybeAddInstantAppInstaller(result, intent,
+ return liveComputer().maybeAddInstantAppInstaller(result, intent,
resolvedType, flags, userId, resolveForStart,
isRequesterInstantApp);
}
@@ -9898,7 +9962,7 @@
private CrossProfileDomainInfo getCrossProfileDomainPreferredLpr(Intent intent,
String resolvedType, int flags, int sourceUserId, int parentUserId) {
- return computer(true).getCrossProfileDomainPreferredLpr(intent,
+ return liveComputer().getCrossProfileDomainPreferredLpr(intent,
resolvedType, flags, sourceUserId, parentUserId);
}
@@ -9907,11 +9971,11 @@
* INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER, which is the worse.
*/
private int bestDomainVerificationStatus(int status1, int status2) {
- return computer(true).bestDomainVerificationStatus(status1, status2);
+ return liveComputer().bestDomainVerificationStatus(status1, status2);
}
private boolean isUserEnabled(int userId) {
- return computer(true).isUserEnabled(userId);
+ return liveComputer().isUserEnabled(userId);
}
/**
@@ -9920,7 +9984,7 @@
* @return filtered list
*/
private List<ResolveInfo> filterIfNotSystemUser(List<ResolveInfo> resolveInfos, int userId) {
- return computer(true).filterIfNotSystemUser(resolveInfos, userId);
+ return liveComputer().filterIfNotSystemUser(resolveInfos, userId);
}
/**
@@ -9937,7 +10001,7 @@
private List<ResolveInfo> applyPostResolutionFilter(@NonNull List<ResolveInfo> resolveInfos,
String ephemeralPkgName, boolean allowDynamicSplits, int filterCallingUid,
boolean resolveForStart, int userId, Intent intent) {
- return computer(true).applyPostResolutionFilter(resolveInfos,
+ return liveComputer().applyPostResolutionFilter(resolveInfos,
ephemeralPkgName, allowDynamicSplits, filterCallingUid,
resolveForStart, userId, intent);
}
@@ -9951,7 +10015,7 @@
*/
private @Nullable ComponentName findInstallFailureActivity(
String packageName, int filterCallingUid, int userId) {
- return computer(true).findInstallFailureActivity(
+ return liveComputer().findInstallFailureActivity(
packageName, filterCallingUid, userId);
}
@@ -9960,13 +10024,13 @@
* @return if the list contains a resolve info with non-negative priority
*/
private boolean hasNonNegativePriority(List<ResolveInfo> resolveInfos) {
- return computer(true).hasNonNegativePriority(resolveInfos);
+ return liveComputer().hasNonNegativePriority(resolveInfos);
}
private List<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPr(Intent intent,
int matchFlags, List<ResolveInfo> candidates, CrossProfileDomainInfo xpDomainInfo,
int userId) {
- return computer(true).filterCandidatesWithDomainPreferredActivitiesLPr(intent,
+ return liveComputer().filterCandidatesWithDomainPreferredActivitiesLPr(intent,
matchFlags, candidates, xpDomainInfo,
userId);
}
@@ -9974,7 +10038,7 @@
private ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
Intent intent, int matchFlags, List<ResolveInfo> candidates,
CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
- return computer(true).filterCandidatesWithDomainPreferredActivitiesLPrBody(
+ return liveComputer().filterCandidatesWithDomainPreferredActivitiesLPrBody(
intent, matchFlags, candidates,
xpDomainInfo, userId, debug);
}
@@ -9984,13 +10048,13 @@
// high 'int'-sized word: link status: undefined/ask/never/always.
// low 'int'-sized word: relative priority among 'always' results.
private long getDomainVerificationStatusLPr(PackageSetting ps, int userId) {
- return computer(true).getDomainVerificationStatusLPr(ps, userId);
+ return liveComputer().getDomainVerificationStatusLPr(ps, userId);
}
private ResolveInfo querySkipCurrentProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
int flags, int sourceUserId) {
- return computer(true).querySkipCurrentProfileIntents(
+ return liveComputer().querySkipCurrentProfileIntents(
matchingFilters, intent, resolvedType,
flags, sourceUserId);
}
@@ -9999,7 +10063,7 @@
private ResolveInfo queryCrossProfileIntents(
List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType,
int flags, int sourceUserId, boolean matchInCurrentProfile) {
- return computer(true).queryCrossProfileIntents(
+ return liveComputer().queryCrossProfileIntents(
matchingFilters, intent, resolvedType,
flags, sourceUserId, matchInCurrentProfile);
}
@@ -10011,13 +10075,13 @@
*/
private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter, Intent intent,
String resolvedType, int flags, int sourceUserId) {
- return computer(true).createForwardingResolveInfo(filter, intent,
+ return liveComputer().createForwardingResolveInfo(filter, intent,
resolvedType, flags, sourceUserId);
}
private ResolveInfo createForwardingResolveInfoUnchecked(IntentFilter filter,
int sourceUserId, int targetUserId) {
- return computer(true).createForwardingResolveInfoUnchecked(filter,
+ return liveComputer().createForwardingResolveInfoUnchecked(filter,
sourceUserId, targetUserId);
}
@@ -10337,7 +10401,7 @@
private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
String resolvedType, int flags, int userId, int callingUid,
boolean includeInstantApps) {
- return computer(true).queryIntentServicesInternal(intent,
+ return liveComputer().queryIntentServicesInternal(intent,
resolvedType, flags, userId, callingUid,
includeInstantApps);
}
@@ -10345,14 +10409,14 @@
private @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
String resolvedType, int flags, int userId, int callingUid,
String instantAppPkgName) {
- return computer(true).queryIntentServicesInternalBody(intent,
+ return liveComputer().queryIntentServicesInternalBody(intent,
resolvedType, flags, userId, callingUid,
instantAppPkgName);
}
private List<ResolveInfo> applyPostServiceResolutionFilter(List<ResolveInfo> resolveInfos,
String instantAppPkgName, @UserIdInt int userId, int filterCallingUid) {
- return computer(true).applyPostServiceResolutionFilter(resolveInfos,
+ return liveComputer().applyPostServiceResolutionFilter(resolveInfos,
instantAppPkgName, userId, filterCallingUid);
}
@@ -10498,13 +10562,12 @@
@Override
public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
- // SNAPSHOT
- return computer(false).getInstalledPackages(flags, userId);
+ return snapshotComputer().getInstalledPackages(flags, userId);
}
private ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
int callingUid) {
- return computer(true).getInstalledPackagesBody(flags, userId,
+ return liveComputer().getInstalledPackagesBody(flags, userId,
callingUid);
}
@@ -10682,19 +10745,18 @@
@Override
public boolean isInstantApp(String packageName, int userId) {
- // SNAPSHOT
- return computer(false).isInstantApp(packageName, userId);
+ return snapshotComputer().isInstantApp(packageName, userId);
}
private boolean isInstantAppInternal(String packageName, @UserIdInt int userId,
int callingUid) {
- return computer(true).isInstantAppInternal(packageName, userId,
+ return liveComputer().isInstantAppInternal(packageName, userId,
callingUid);
}
private boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId,
int callingUid) {
- return computer(true).isInstantAppInternalBody(packageName, userId,
+ return liveComputer().isInstantAppInternalBody(packageName, userId,
callingUid);
}
@@ -10752,7 +10814,7 @@
}
private boolean isCallerSameApp(String packageName, int uid) {
- return computer(true).isCallerSameApp(packageName, uid);
+ return liveComputer().isCallerSameApp(packageName, uid);
}
@Override
@@ -11510,7 +11572,7 @@
*/
void enforceCrossUserPermission(int callingUid, @UserIdInt int userId,
boolean requireFullPermission, boolean checkShell, String message) {
- computer(true).enforceCrossUserPermission(callingUid, userId,
+ liveComputer().enforceCrossUserPermission(callingUid, userId,
requireFullPermission, checkShell, message);
}
@@ -11527,7 +11589,7 @@
private void enforceCrossUserPermission(int callingUid, @UserIdInt int userId,
boolean requireFullPermission, boolean checkShell,
boolean requirePermissionWhenSameUser, String message) {
- computer(true).enforceCrossUserPermission(callingUid, userId,
+ liveComputer().enforceCrossUserPermission(callingUid, userId,
requireFullPermission, checkShell,
requirePermissionWhenSameUser, message);
}
@@ -11548,24 +11610,24 @@
*/
private void enforceCrossUserOrProfilePermission(int callingUid, @UserIdInt int userId,
boolean requireFullPermission, boolean checkShell, String message) {
- computer(true).enforceCrossUserOrProfilePermission(callingUid, userId,
+ liveComputer().enforceCrossUserOrProfilePermission(callingUid, userId,
requireFullPermission, checkShell, message);
}
private boolean hasCrossUserPermission(
int callingUid, int callingUserId, int userId, boolean requireFullPermission,
boolean requirePermissionWhenSameUser) {
- return computer(true).hasCrossUserPermission(
+ return liveComputer().hasCrossUserPermission(
callingUid, callingUserId, userId, requireFullPermission,
requirePermissionWhenSameUser);
}
private boolean hasPermission(String permission) {
- return computer(true).hasPermission(permission);
+ return liveComputer().hasPermission(permission);
}
private boolean isSameProfileGroup(@UserIdInt int callerUserId, @UserIdInt int userId) {
- return computer(true).isSameProfileGroup(callerUserId, userId);
+ return liveComputer().isSameProfileGroup(callerUserId, userId);
}
private static String buildInvalidCrossUserPermissionMessage(int callingUid,
@@ -12203,7 +12265,7 @@
@Nullable
private SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
- return computer(true).getSharedLibraryInfoLPr(name, version);
+ return liveComputer().getSharedLibraryInfoLPr(name, version);
}
@Nullable
@@ -17321,15 +17383,7 @@
// send to integrity component only.
integrityVerification.setPackage("android");
- DeviceIdleInternal idleController =
- mInjector.getLocalService(DeviceIdleInternal.class);
- final long idleDuration = getVerificationTimeout();
-
- idleController.addPowerSaveTempWhitelistAppDirect(Process.myUid(),
- idleDuration,
- false, "integrity component");
final BroadcastOptions options = BroadcastOptions.makeBasic();
- options.setTemporaryAppWhitelistDuration(idleDuration);
mContext.sendOrderedBroadcastAsUser(integrityVerification, UserHandle.SYSTEM,
/* receiverPermission= */ null,
@@ -20634,17 +20688,17 @@
}
private String resolveExternalPackageNameLPr(AndroidPackage pkg) {
- return computer(true).resolveExternalPackageNameLPr(pkg);
+ return liveComputer().resolveExternalPackageNameLPr(pkg);
}
@GuardedBy("mLock")
private String resolveInternalPackageNameLPr(String packageName, long versionCode) {
- return computer(true).resolveInternalPackageNameLPr(packageName, versionCode);
+ return liveComputer().resolveInternalPackageNameLPr(packageName, versionCode);
}
private String resolveInternalPackageNameInternalLocked(
String packageName, long versionCode, int callingUid) {
- return computer(true).resolveInternalPackageNameInternalLocked(
+ return liveComputer().resolveInternalPackageNameInternalLocked(
packageName, versionCode, callingUid);
}
@@ -22695,11 +22749,11 @@
* then reports the most likely home activity or null if there are more than one.
*/
private ComponentName getDefaultHomeActivity(int userId) {
- return computer(true).getDefaultHomeActivity(userId);
+ return liveComputer().getDefaultHomeActivity(userId);
}
private Intent getHomeIntent() {
- return computer(true).getHomeIntent();
+ return liveComputer().getHomeIntent();
}
private IntentFilter getHomeFilter() {
@@ -22711,7 +22765,7 @@
ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
int userId) {
- return computer(true).getHomeActivitiesAsUser(allHomeCandidates,
+ return liveComputer().getHomeActivitiesAsUser(allHomeCandidates,
userId);
}
@@ -23767,7 +23821,7 @@
// Clear cache on flags changes.
DeviceConfig.addOnPropertiesChangedListener(
- NAMESPACE_PACKAGE_MANAGER_SERVICE, FgThread.getExecutor(),
+ NAMESPACE_PACKAGE_MANAGER_SERVICE, mInjector.getBackgroundExecutor(),
properties -> {
final Set<String> keyset = properties.getKeyset();
if (keyset.contains(PROPERTY_INCFS_DEFAULT_TIMEOUTS) || keyset.contains(
@@ -26326,13 +26380,11 @@
}
private AndroidPackage getPackage(String packageName) {
- // SNAPSHOT
- return computer(false).getPackage(packageName);
+ return snapshotComputer().getPackage(packageName);
}
private AndroidPackage getPackage(int uid) {
- // SNAPSHOT
- return computer(false).getPackage(uid);
+ return snapshotComputer().getPackage(uid);
}
private class PackageManagerInternalImpl extends PackageManagerInternal {
@@ -27496,6 +27548,13 @@
requestChecksumsInternal(packageName, includeSplits, optional, required,
trustedInstallers, statusReceiver, userId, executor, handler);
}
+
+ @Override
+ public boolean isPackageFrozen(@NonNull String packageName,
+ int callingUid, int userId) {
+ return PackageManagerService.this.getPackageStartability(
+ packageName, callingUid, userId) == PACKAGE_STARTABILITY_FROZEN;
+ }
}
@@ -27583,12 +27642,11 @@
@Nullable
public PackageSetting getPackageSetting(String packageName) {
- // SNAPSHOT
- return computer(false).getPackageSetting(packageName);
+ return snapshotComputer().getPackageSetting(packageName);
}
private PackageSetting getPackageSettingInternal(String packageName, int callingUid) {
- return computer(true).getPackageSettingInternal(packageName, callingUid);
+ return liveComputer().getPackageSettingInternal(packageName, callingUid);
}
void forEachPackage(Consumer<AndroidPackage> actionLocked) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e20ed05..19a94b3 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4762,13 +4762,32 @@
final boolean hasParent = user.profileGroupId != user.id
&& user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID;
if (verbose) {
- pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s%s\n", i, user.id, user.name,
+ final DevicePolicyManagerInternal dpm = getDevicePolicyManagerInternal();
+ String deviceOwner = "";
+ String profileOwner = "";
+ if (dpm != null) {
+ final long ident = Binder.clearCallingIdentity();
+ // NOTE: dpm methods below CANNOT be called while holding the mUsersLock
+ try {
+ if (dpm.getDeviceOwnerUserId() == user.id) {
+ deviceOwner = " (device-owner)";
+ }
+ if (dpm.getProfileOwnerAsUser(user.id) != null) {
+ profileOwner = " (profile-owner)";
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s%s%s%s\n", i, user.id,
+ user.name,
UserInfo.flagsToString(user.flags),
hasParent ? " (parentId=" + user.profileGroupId + ")" : "",
running ? " (running)" : "",
user.partial ? " (partial)" : "",
user.preCreated ? " (pre-created)" : "",
user.convertedFromPreCreated ? " (converted)" : "",
+ deviceOwner, profileOwner,
current ? " (current)" : "");
} else {
// NOTE: the standard "list users" command is used by integration tests and
diff --git a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
index 6886985..c1744d8 100644
--- a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
+++ b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
@@ -114,7 +114,7 @@
intent.setPackage(context.getPackageName());
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mBurnInProtectionIntent = PendingIntent.getBroadcast(context, 0,
- intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
DisplayManager displayManager =
(DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
mDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index aa2e1ff..7caf739 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
+import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.content.Context.CONTEXT_RESTRICTED;
@@ -2191,6 +2192,11 @@
== PERMISSION_GRANTED) ? ADD_OKAY : ADD_PERMISSION_DENIED;
}
+ if (mContext.checkCallingOrSelfPermission(SYSTEM_APPLICATION_OVERLAY)
+ == PERMISSION_GRANTED) {
+ return ADD_OKAY;
+ }
+
// check if user has enabled this operation. SecurityException will be thrown if this app
// has not been allowed by the user. The reason to use "noteOp" (instead of checkOp) is to
// make sure the usage is logged.
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
deleted file mode 100644
index b95c5efc..0000000
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.policy.role;
-
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-import android.app.role.RoleManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
-import android.content.pm.ResolveInfo;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.internal.R;
-import com.android.internal.telephony.SmsApplication;
-import com.android.internal.util.CollectionUtils;
-import com.android.server.LocalServices;
-import com.android.server.role.LegacyRoleHolderProvider;
-import com.android.server.role.RoleManagerService;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Logic to retrieve the various legacy(pre-Q) equivalents of role holders.
- *
- * Unlike {@link RoleManagerService} this is meant to be pretty high-level to allow for depending
- * on all kinds of various systems that are historically involved in legacy role resolution,
- * e.g. {@link SmsApplication}
- *
- * @see RoleManagerService#migrateRoleIfNecessary
- */
-public class LegacyRoleResolutionPolicy implements LegacyRoleHolderProvider {
-
- private static final boolean DEBUG = false;
- private static final String LOG_TAG = "LegacyRoleResolutionPol";
-
- @NonNull
- private final Context mContext;
-
- public LegacyRoleResolutionPolicy(@NonNull Context context) {
- mContext = context;
- }
-
- @NonNull
- @Override
- public List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId) {
- switch (roleName) {
- case RoleManager.ROLE_ASSISTANT: {
- String packageName;
- String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- Settings.Secure.ASSISTANT, userId);
- // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is
- // null, while only an empty string means user selected "None".
- if (setting != null) {
- if (!setting.isEmpty()) {
- ComponentName componentName = ComponentName.unflattenFromString(setting);
- packageName = componentName != null ? componentName.getPackageName() : null;
- } else {
- packageName = null;
- }
- } else if (mContext.getPackageManager().isDeviceUpgrading()) {
- String defaultAssistant = mContext.getString(R.string.config_defaultAssistant);
- packageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null;
- } else {
- packageName = null;
- }
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_BROWSER: {
- PackageManagerInternal packageManagerInternal = LocalServices.getService(
- PackageManagerInternal.class);
- String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName(
- userId);
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_DIALER: {
- String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- Settings.Secure.DIALER_DEFAULT_APPLICATION, userId);
- String packageName;
- if (!TextUtils.isEmpty(setting)) {
- packageName = setting;
- } else if (mContext.getPackageManager().isDeviceUpgrading()) {
- // DefaultDialerManager was using the default dialer app if
- // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
- // TelecomManager.getSystemDialerPackage() won't work because it might not
- // be ready.
- packageName = mContext.getString(R.string.config_defaultDialer);
- } else {
- packageName = null;
- }
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_SMS: {
- String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
- String packageName;
- if (!TextUtils.isEmpty(setting)) {
- packageName = setting;
- } else if (mContext.getPackageManager().isDeviceUpgrading()) {
- // SmsApplication was using the default SMS app if
- // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
- packageName = mContext.getString(R.string.config_defaultSms);
- } else {
- packageName = null;
- }
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_HOME: {
- PackageManager packageManager = mContext.getPackageManager();
- String packageName;
- if (packageManager.isDeviceUpgrading()) {
- ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(
- new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),
- PackageManager.MATCH_DEFAULT_ONLY
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
- packageName = resolveInfo != null && resolveInfo.activityInfo != null
- ? resolveInfo.activityInfo.packageName : null;
- if (packageName != null && isSettingsApplication(packageName, userId)) {
- packageName = null;
- }
- } else {
- packageName = null;
- }
- return CollectionUtils.singletonOrEmpty(packageName);
- }
- case RoleManager.ROLE_EMERGENCY: {
- String defaultEmergencyApp = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId);
- return CollectionUtils.singletonOrEmpty(defaultEmergencyApp);
- }
- default: {
- Slog.e(LOG_TAG, "Don't know how to find legacy role holders for " + roleName);
- return Collections.emptyList();
- }
- }
- }
-
- private boolean isSettingsApplication(@NonNull String packageName, @UserIdInt int userId) {
- PackageManager packageManager = mContext.getPackageManager();
- ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(new Intent(
- Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
- if (resolveInfo == null || resolveInfo.activityInfo == null) {
- return false;
- }
- return Objects.equals(packageName, resolveInfo.activityInfo.packageName);
- }
-}
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleStateProviderImpl.java b/services/core/java/com/android/server/policy/role/LegacyRoleStateProviderImpl.java
new file mode 100644
index 0000000..097f332
--- /dev/null
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleStateProviderImpl.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy.role;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.role.RoleManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
+import android.os.Environment;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.R;
+import com.android.server.LocalServices;
+import com.android.server.role.LegacyRoleStateProvider;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Implementation to provide legacy role state.
+ */
+public class LegacyRoleStateProviderImpl implements LegacyRoleStateProvider {
+ private static final String LOG_TAG = "LegacyRoleState";
+
+ private static final String ROLES_FILE_NAME = "roles.xml";
+
+ private static final String TAG_ROLES = "roles";
+ private static final String TAG_ROLE = "role";
+ private static final String TAG_HOLDER = "holder";
+ private static final String ATTRIBUTE_NAME = "name";
+
+ @NonNull
+ private final Context mContext;
+
+ public LegacyRoleStateProviderImpl(@NonNull Context context) {
+ mContext = context;
+ }
+
+ @NonNull
+ @Override
+ public Map<String, Set<String>> getLegacyRoleState(@UserIdInt int userId) {
+ Map<String, Set<String>> roles = readFile(userId);
+ if (roles == null) {
+ roles = readFromLegacySettings(userId);
+ }
+ return roles;
+ }
+
+ @Nullable
+ private Map<String, Set<String>> readFile(@UserIdInt int userId) {
+ File file = getFile(userId);
+ try (FileInputStream in = new AtomicFile(file).openRead()) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ Map<String, Set<String>> roles = parseXml(parser);
+ Slog.i(LOG_TAG, "Read legacy roles.xml successfully");
+ return roles;
+ } catch (FileNotFoundException e) {
+ Slog.i(LOG_TAG, "Legacy roles.xml not found");
+ return null;
+ } catch (XmlPullParserException | IOException e) {
+ Slog.wtf(LOG_TAG, "Failed to parse legacy roles.xml: " + file, e);
+ return null;
+ }
+ }
+
+ @NonNull
+ private Map<String, Set<String>> parseXml(@NonNull XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ int type;
+ int depth;
+ int innerDepth = parser.getDepth() + 1;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+ if (depth > innerDepth || type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (parser.getName().equals(TAG_ROLES)) {
+ return parseRoles(parser);
+ }
+ }
+
+ throw new IOException("Missing <" + TAG_ROLES + "> in roles.xml");
+ }
+
+ @NonNull
+ private Map<String, Set<String>> parseRoles(@NonNull XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ Map<String, Set<String>> roles = new ArrayMap<>();
+
+ int type;
+ int depth;
+ int innerDepth = parser.getDepth() + 1;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+ if (depth > innerDepth || type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (parser.getName().equals(TAG_ROLE)) {
+ String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ Set<String> roleHolders = parseRoleHoldersLocked(parser);
+ roles.put(roleName, roleHolders);
+ }
+ }
+
+ return roles;
+ }
+
+ @NonNull
+ private Set<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ Set<String> roleHolders = new ArraySet<>();
+
+ int type;
+ int depth;
+ int innerDepth = parser.getDepth() + 1;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+ if (depth > innerDepth || type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (parser.getName().equals(TAG_HOLDER)) {
+ String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+ roleHolders.add(roleHolder);
+ }
+ }
+
+ return roleHolders;
+ }
+
+ @NonNull
+ private static File getFile(@UserIdInt int userId) {
+ return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME);
+ }
+
+ @NonNull
+ private Map<String, Set<String>> readFromLegacySettings(@UserIdInt int userId) {
+ Map<String, Set<String>> roles = new ArrayMap<>();
+
+ // Assistant
+ ContentResolver contentResolver = mContext.getContentResolver();
+ String assistantSetting = Settings.Secure.getStringForUser(contentResolver,
+ Settings.Secure.ASSISTANT, userId);
+ PackageManager packageManager = mContext.getPackageManager();
+ String assistantPackageName;
+ // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is
+ // null, while only an empty string means user selected "None".
+ if (assistantSetting != null) {
+ if (!assistantSetting.isEmpty()) {
+ ComponentName componentName = ComponentName.unflattenFromString(assistantSetting);
+ assistantPackageName = componentName != null ? componentName.getPackageName()
+ : null;
+ } else {
+ assistantPackageName = null;
+ }
+ } else if (packageManager.isDeviceUpgrading()) {
+ String defaultAssistant = mContext.getString(R.string.config_defaultAssistant);
+ assistantPackageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null;
+ } else {
+ assistantPackageName = null;
+ }
+ if (assistantPackageName != null) {
+ roles.put(RoleManager.ROLE_ASSISTANT, Collections.singleton(assistantPackageName));
+ }
+
+ // Browser
+ PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ String browserPackageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName(
+ userId);
+ if (browserPackageName != null) {
+ roles.put(RoleManager.ROLE_BROWSER, Collections.singleton(browserPackageName));
+ }
+
+ // Dialer
+ String dialerSetting = Settings.Secure.getStringForUser(contentResolver,
+ Settings.Secure.DIALER_DEFAULT_APPLICATION, userId);
+ String dialerPackageName;
+ if (!TextUtils.isEmpty(dialerSetting)) {
+ dialerPackageName = dialerSetting;
+ } else if (packageManager.isDeviceUpgrading()) {
+ // DefaultDialerManager was using the default dialer app if
+ // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
+ // TelecomManager.getSystemDialerPackage() won't work because it might not
+ // be ready.
+ dialerPackageName = mContext.getString(R.string.config_defaultDialer);
+ } else {
+ dialerPackageName = null;
+ }
+ if (dialerPackageName != null) {
+ roles.put(RoleManager.ROLE_DIALER, Collections.singleton(dialerPackageName));
+ }
+
+ // SMS
+ String smsSetting = Settings.Secure.getStringForUser(contentResolver,
+ Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
+ String smsPackageName;
+ if (!TextUtils.isEmpty(smsSetting)) {
+ smsPackageName = smsSetting;
+ } else if (mContext.getPackageManager().isDeviceUpgrading()) {
+ // SmsApplication was using the default SMS app if
+ // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
+ smsPackageName = mContext.getString(R.string.config_defaultSms);
+ } else {
+ smsPackageName = null;
+ }
+ if (smsPackageName != null) {
+ roles.put(RoleManager.ROLE_SMS, Collections.singleton(smsPackageName));
+ }
+
+ // Home
+ String homePackageName;
+ if (packageManager.isDeviceUpgrading()) {
+ ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(
+ new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),
+ PackageManager.MATCH_DEFAULT_ONLY
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ homePackageName = resolveInfo != null && resolveInfo.activityInfo != null
+ ? resolveInfo.activityInfo.packageName : null;
+ if (homePackageName != null && isSettingsApplication(homePackageName, userId)) {
+ homePackageName = null;
+ }
+ } else {
+ homePackageName = null;
+ }
+ if (homePackageName != null) {
+ roles.put(RoleManager.ROLE_HOME, Collections.singleton(homePackageName));
+ }
+
+ // Emergency
+ String emergencyPackageName = Settings.Secure.getStringForUser(contentResolver,
+ Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId);
+ if (emergencyPackageName != null) {
+ roles.put(RoleManager.ROLE_EMERGENCY, Collections.singleton(emergencyPackageName));
+ }
+
+ return roles;
+ }
+
+ private boolean isSettingsApplication(@NonNull String packageName, @UserIdInt int userId) {
+ PackageManager packageManager = mContext.getPackageManager();
+ ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(new Intent(
+ Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ if (resolveInfo == null || resolveInfo.activityInfo == null) {
+ return false;
+ }
+ return Objects.equals(packageName, resolveInfo.activityInfo.packageName);
+ }
+}
diff --git a/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java b/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java
deleted file mode 100644
index ed0d675..0000000
--- a/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.role;
-
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-
-import java.util.List;
-
-/**
- * A provider for migrating legacy "role"s to their actual role implementation.
- */
-//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
-public interface LegacyRoleHolderProvider {
- /**
- * Get the list of holders of a legacy "role" before its actual role is introduced.
- * <p>
- * This method will only be called for the first time a role is made available in the platform.
- *
- * @param roleName the name of the role
- * @param userId the user ID
- * @return a list of holders for the given role
- */
- @NonNull
- List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId);
-}
diff --git a/services/core/java/com/android/server/role/LegacyRoleStateProvider.java b/services/core/java/com/android/server/role/LegacyRoleStateProvider.java
new file mode 100644
index 0000000..ec4cfc1
--- /dev/null
+++ b/services/core/java/com/android/server/role/LegacyRoleStateProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.role;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provider for legacy role state.
+ * <p>
+ * The role state may come from two sources, either the different pre-role default app settings, or
+ * the pre-modularization roles.xml file stored in platform.
+ *
+ * @hide
+ */
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public interface LegacyRoleStateProvider {
+ /**
+ * Get the legacy role state stored in the platform.
+ *
+ * @param userId the user ID
+ * @return a mapping of role name to its set of holders
+ */
+ @NonNull
+ Map<String, Set<String>> getLegacyRoleState(@UserIdInt int userId);
+}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 4e42f16..bc5ddd3 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -103,7 +103,7 @@
private final Object mLock = new Object();
@NonNull
- private final LegacyRoleHolderProvider mLegacyRoleHolderProvider;
+ private final LegacyRoleStateProvider mLegacyRoleStateProvider;
/**
* Maps user id to its state.
@@ -139,10 +139,10 @@
new SparseArray<>();
public RoleManagerService(@NonNull Context context,
- @NonNull LegacyRoleHolderProvider legacyRoleHolderProvider) {
+ @NonNull LegacyRoleStateProvider legacyRoleStateProvider) {
super(context);
- mLegacyRoleHolderProvider = legacyRoleHolderProvider;
+ mLegacyRoleStateProvider = legacyRoleStateProvider;
RoleControllerManager.initializeRemoteServiceComponentName(context);
@@ -241,16 +241,6 @@
return AndroidFuture.completedFuture(null);
}
- //TODO gradually add more role migrations statements here for remaining roles
- // Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders
- // for a given role before adding a migration statement for it here
- maybeMigrateRole(RoleManager.ROLE_ASSISTANT, userId);
- maybeMigrateRole(RoleManager.ROLE_BROWSER, userId);
- maybeMigrateRole(RoleManager.ROLE_DIALER, userId);
- maybeMigrateRole(RoleManager.ROLE_SMS, userId);
- maybeMigrateRole(RoleManager.ROLE_EMERGENCY, userId);
- maybeMigrateRole(RoleManager.ROLE_HOME, userId);
-
// Some package state has changed, so grant default roles again.
Slog.i(LOG_TAG, "Granting default roles...");
AndroidFuture<Void> future = new AndroidFuture<>();
@@ -266,23 +256,6 @@
return future;
}
- private void maybeMigrateRole(String role, @UserIdInt int userId) {
- // Any role for which we have a record are already migrated
- RoleUserState userState = getOrCreateUserState(userId);
- if (!userState.isRoleAvailable(role)) {
- List<String> roleHolders = mLegacyRoleHolderProvider.getLegacyRoleHolders(role, userId);
- if (roleHolders.isEmpty()) {
- return;
- }
- Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders);
- userState.addRoleName(role);
- int size = roleHolders.size();
- for (int i = 0; i < size; i++) {
- userState.addRoleHolder(role, roleHolders.get(i));
- }
- }
- }
-
@Nullable
private String computePackageStateHash(@UserIdInt int userId) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@@ -327,7 +300,7 @@
synchronized (mLock) {
RoleUserState userState = mUserStates.get(userId);
if (userState == null) {
- userState = new RoleUserState(userId, this);
+ userState = new RoleUserState(userId, mLegacyRoleStateProvider, this);
mUserStates.put(userId, userState);
}
return userState;
@@ -663,7 +636,7 @@
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
}
- if (mPackageManagerInternal.getInstantAppPackageName(callingUid) != null) {
+ if (isInstantApp(callingUid)) {
return null;
}
@@ -676,6 +649,25 @@
}
}
+ private boolean isInstantApp(int uid) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final UserHandle user = UserHandle.getUserHandleForUid(uid);
+ final Context userContext = getContext().createContextAsUser(user, 0);
+ final PackageManager userPackageManager = userContext.getPackageManager();
+ // Instant apps can not have shared UID, so it's safe to check only the first
+ // package name here.
+ final String packageName = ArrayUtils.firstOrNull(
+ userPackageManager.getPackagesForUid(uid));
+ if (packageName == null) {
+ return false;
+ }
+ return userPackageManager.isInstantApp(packageName);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@Override
public boolean setBrowserRoleHolder(@Nullable String packageName, @UserIdInt int userId) {
final Context context = getContext();
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index 3a5ed5c..f5a79ea 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -21,14 +21,11 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
-import android.os.Environment;
import android.os.Handler;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.AtomicFile;
import android.util.Slog;
-import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
@@ -38,13 +35,6 @@
import com.android.role.persistence.RolesPersistence;
import com.android.role.persistence.RolesState;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -59,23 +49,17 @@
public static final int VERSION_UNDEFINED = -1;
- private static final String ROLES_FILE_NAME = "roles.xml";
-
private static final long WRITE_DELAY_MILLIS = 200;
- private static final String TAG_ROLES = "roles";
- private static final String TAG_ROLE = "role";
- private static final String TAG_HOLDER = "holder";
- private static final String ATTRIBUTE_VERSION = "version";
- private static final String ATTRIBUTE_NAME = "name";
- private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash";
-
private final RolesPersistence mPersistence = RolesPersistence.createInstance();
@UserIdInt
private final int mUserId;
@NonNull
+ private final LegacyRoleStateProvider mLegacyStateProvider;
+
+ @NonNull
private final Callback mCallback;
@NonNull
@@ -108,10 +92,13 @@
* Create a new user state, and read its state from disk if previously persisted.
*
* @param userId the user id for this user state
+ * @param legacyStateProvider the provider for legacy role state
* @param callback the callback for this user state
*/
- public RoleUserState(@UserIdInt int userId, @NonNull Callback callback) {
+ public RoleUserState(@UserIdInt int userId,
+ @NonNull LegacyRoleStateProvider legacyStateProvider, @NonNull Callback callback) {
mUserId = userId;
+ mLegacyStateProvider = legacyStateProvider;
mCallback = callback;
readFile();
@@ -368,102 +355,27 @@
private void readFile() {
synchronized (mLock) {
- RolesState roles = mPersistence.readForUser(UserHandle.of(mUserId));
- if (roles == null) {
- readLegacyFileLocked();
- scheduleWriteFileLocked();
- return;
+ RolesState roleState = mPersistence.readForUser(UserHandle.of(mUserId));
+
+ Map<String, Set<String>> roles;
+ if (roleState != null) {
+ mVersion = roleState.getVersion();
+ mPackagesHash = roleState.getPackagesHash();
+ roles = roleState.getRoles();
+ } else {
+ roles = mLegacyStateProvider.getLegacyRoleState(mUserId);
}
-
- mVersion = roles.getVersion();
- mPackagesHash = roles.getPackagesHash();
-
mRoles.clear();
- for (Map.Entry<String, Set<String>> entry : roles.getRoles().entrySet()) {
+ for (Map.Entry<String, Set<String>> entry : roles.entrySet()) {
String roleName = entry.getKey();
ArraySet<String> roleHolders = new ArraySet<>(entry.getValue());
mRoles.put(roleName, roleHolders);
}
- }
- }
- private void readLegacyFileLocked() {
- File file = getFile(mUserId);
- try (FileInputStream in = new AtomicFile(file).openRead()) {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(in, null);
- parseXmlLocked(parser);
- Slog.i(LOG_TAG, "Read roles.xml successfully");
- } catch (FileNotFoundException e) {
- Slog.i(LOG_TAG, "roles.xml not found");
- } catch (XmlPullParserException | IOException e) {
- throw new IllegalStateException("Failed to parse roles.xml: " + file, e);
- }
- }
-
- private void parseXmlLocked(@NonNull XmlPullParser parser) throws IOException,
- XmlPullParserException {
- int type;
- int depth;
- int innerDepth = parser.getDepth() + 1;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
- if (depth > innerDepth || type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (parser.getName().equals(TAG_ROLES)) {
- parseRolesLocked(parser);
- return;
+ if (roleState == null) {
+ scheduleWriteFileLocked();
}
}
- Slog.w(LOG_TAG, "Missing <" + TAG_ROLES + "> in roles.xml");
- }
-
- private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
- XmlPullParserException {
- mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
- mPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
- mRoles.clear();
-
- int type;
- int depth;
- int innerDepth = parser.getDepth() + 1;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
- if (depth > innerDepth || type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (parser.getName().equals(TAG_ROLE)) {
- String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
- ArraySet<String> roleHolders = parseRoleHoldersLocked(parser);
- mRoles.put(roleName, roleHolders);
- }
- }
- }
-
- @NonNull
- private ArraySet<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser)
- throws IOException, XmlPullParserException {
- ArraySet<String> roleHolders = new ArraySet<>();
-
- int type;
- int depth;
- int innerDepth = parser.getDepth() + 1;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
- if (depth > innerDepth || type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (parser.getName().equals(TAG_HOLDER)) {
- String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME);
- roleHolders.add(roleHolder);
- }
- }
-
- return roleHolders;
}
/**
@@ -549,11 +461,6 @@
}
}
- @NonNull
- private static File getFile(@UserIdInt int userId) {
- return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME);
- }
-
/**
* Callback for a user state.
*/
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index d656617..e7cda02 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -141,6 +141,7 @@
import com.android.internal.os.KernelCpuThreadReader;
import com.android.internal.os.KernelCpuThreadReaderDiff;
import com.android.internal.os.KernelCpuThreadReaderSettingsObserver;
+import com.android.internal.os.KernelCpuTotalBpfMapReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
@@ -350,6 +351,7 @@
private final Object mDataBytesTransferLock = new Object();
private final Object mBluetoothBytesTransferLock = new Object();
private final Object mKernelWakelockLock = new Object();
+ private final Object mCpuTimePerClusterFreqLock = new Object();
private final Object mCpuTimePerUidLock = new Object();
private final Object mCpuTimePerUidFreqLock = new Object();
private final Object mCpuActiveTimeLock = new Object();
@@ -438,6 +440,10 @@
synchronized (mKernelWakelockLock) {
return pullKernelWakelockLocked(atomTag, data);
}
+ case FrameworkStatsLog.CPU_TIME_PER_CLUSTER_FREQ:
+ synchronized (mCpuTimePerClusterFreqLock) {
+ return pullCpuTimePerClusterFreqLocked(atomTag, data);
+ }
case FrameworkStatsLog.CPU_TIME_PER_UID:
synchronized (mCpuTimePerUidLock) {
return pullCpuTimePerUidLocked(atomTag, data);
@@ -773,6 +779,7 @@
mStatsCallbackImpl = new StatsPullAtomCallbackImpl();
registerBluetoothBytesTransfer();
registerKernelWakelock();
+ registerCpuTimePerClusterFreq();
registerCpuTimePerUid();
registerCpuCyclesPerUidCluster();
registerCpuTimePerUidFreq();
@@ -1444,6 +1451,31 @@
return StatsManager.PULL_SUCCESS;
}
+ private void registerCpuTimePerClusterFreq() {
+ if (KernelCpuTotalBpfMapReader.isSupported()) {
+ int tagId = FrameworkStatsLog.CPU_TIME_PER_CLUSTER_FREQ;
+ PullAtomMetadata metadata = new PullAtomMetadata.Builder()
+ .setAdditiveFields(new int[] {3})
+ .build();
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ metadata,
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl
+ );
+ }
+ }
+
+ int pullCpuTimePerClusterFreqLocked(int atomTag, List<StatsEvent> pulledData) {
+ boolean success = KernelCpuTotalBpfMapReader.read((cluster, freq, timeMs) -> {
+ pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
+ });
+ if (!success) {
+ return StatsManager.PULL_SKIP;
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
private void registerCpuTimePerUid() {
int tagId = FrameworkStatsLog.CPU_TIME_PER_UID;
PullAtomMetadata metadata = new PullAtomMetadata.Builder()
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index ebfffec..00ab973b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -40,6 +40,9 @@
void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
+ /** Collapses the notification shade. */
+ void collapsePanels();
+
void dismissKeyboardShortcutsMenu();
void toggleKeyboardShortcutsMenu(int deviceId);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index bd2d382..3ee8dd7 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -19,6 +19,7 @@
import static android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS;
import static android.view.Display.DEFAULT_DISPLAY;
+import android.Manifest;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.app.ITransientNotificationCallback;
@@ -29,6 +30,7 @@
import android.compat.annotation.EnabledSince;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.display.DisplayManager;
@@ -74,6 +76,7 @@
import com.android.server.policy.GlobalActionsProvider;
import com.android.server.power.ShutdownCheckPoints;
import com.android.server.power.ShutdownThread;
+import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -113,6 +116,7 @@
private final Object mLock = new Object();
private final DeathRecipient mDeathRecipient = new DeathRecipient();
+ private final ActivityTaskManagerInternal mActivityTaskManager;
private int mCurrentUserId;
private boolean mTracingEnabled;
@@ -213,6 +217,7 @@
final DisplayManager displayManager =
(DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
displayManager.registerDisplayListener(this, mHandler);
+ mActivityTaskManager = LocalServices.getService(ActivityTaskManagerInternal.class);
}
@Override
@@ -379,6 +384,16 @@
}
@Override
+ public void collapsePanels() {
+ if (mBar != null) {
+ try {
+ mBar.animateCollapsePanels();
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
public void dismissKeyboardShortcutsMenu() {
if (mBar != null) {
try {
@@ -620,10 +635,20 @@
@Override
public void collapsePanels() {
- if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, Binder.getCallingUid())) {
+ int uid = Binder.getCallingUid();
+ int pid = Binder.getCallingPid();
+ if (CompatChanges.isChangeEnabled(LOCK_DOWN_COLLAPSE_STATUS_BAR, uid)) {
enforceStatusBar();
} else {
- enforceExpandStatusBar();
+ if (mContext.checkPermission(Manifest.permission.STATUS_BAR, pid, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ enforceExpandStatusBar();
+ if (!mActivityTaskManager.canCloseSystemDialogs(pid, uid)) {
+ Slog.e(TAG, "Permission Denial: Method collapsePanels() requires permission "
+ + Manifest.permission.STATUS_BAR + ", ignoring call.");
+ return;
+ }
+ }
}
if (mBar != null) {
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 93ba758..753b42b 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -192,7 +192,7 @@
request.getSystemTextClassifierMetadata(),
/* verifyCallingPackage= */ true,
/* attemptToBind= */ true,
- service -> service.onSuggestSelection(sessionId, request, callback),
+ service -> service.onSuggestSelection(sessionId, request, wrap(callback)),
"onSuggestSelection",
callback);
}
@@ -1057,6 +1057,8 @@
rewriteTextClassificationIcons(result);
} else if (parcelled instanceof ConversationActions) {
rewriteConversationActionsIcons(result);
+ } else if (parcelled instanceof TextSelection) {
+ rewriteTextSelectionIcons(result);
} else {
// do nothing.
}
@@ -1067,10 +1069,32 @@
}
}
- private static void rewriteTextClassificationIcons(Bundle result) {
- final TextClassification classification = TextClassifierService.getResponse(result);
+ private static void rewriteTextSelectionIcons(Bundle result) {
+ final TextSelection textSelection = TextClassifierService.getResponse(result);
+ if (textSelection.getTextClassification() == null) {
+ return;
+ }
+ TextClassification newTextClassification =
+ rewriteTextClassificationIcons(textSelection.getTextClassification());
+ if (newTextClassification == null) {
+ return;
+ }
+ TextClassifierService.putResponse(
+ result,
+ textSelection.toBuilder()
+ .setTextClassification(newTextClassification)
+ .build());
+ }
+
+ /**
+ * Returns a new {@link TextClassification} if any modification is made, {@code null}
+ * otherwise.
+ */
+ @Nullable
+ private static TextClassification rewriteTextClassificationIcons(
+ TextClassification textClassification) {
boolean rewrite = false;
- final List<RemoteAction> actions = classification.getActions();
+ final List<RemoteAction> actions = textClassification.getActions();
final int size = actions.size();
final List<RemoteAction> validActions = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
@@ -1084,13 +1108,21 @@
}
validActions.add(validAction);
}
- if (rewrite) {
- TextClassifierService.putResponse(
- result,
- classification.toBuilder()
- .clearActions()
- .addActions(validActions)
- .build());
+ return rewrite
+ ? textClassification
+ .toBuilder()
+ .clearActions()
+ .addActions(validActions)
+ .build()
+ : null;
+ }
+
+ private static void rewriteTextClassificationIcons(Bundle result) {
+ final TextClassification classification = TextClassifierService.getResponse(result);
+ TextClassification newTextClassification = rewriteTextClassificationIcons(
+ classification);
+ if (newTextClassification != null) {
+ TextClassifierService.putResponse(result, newTextClassification);
}
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index d0c6323..2ead3be 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -27,7 +27,6 @@
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
import android.content.Context;
-import android.location.LocationManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -35,7 +34,6 @@
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -335,19 +333,6 @@
return isGeoLocationTimeZoneDetectionEnabled(mContext);
}
- boolean isLocationEnabled(@UserIdInt int userId) {
- enforceManageTimeZoneDetectorPermission();
-
- final long token = mCallerIdentityInjector.clearCallingIdentity();
- try {
- UserHandle user = UserHandle.of(userId);
- LocationManager locationManager = mContext.getSystemService(LocationManager.class);
- return locationManager.isLocationEnabledForUser(user);
- } finally {
- mCallerIdentityInjector.restoreCallingIdentity(token);
- }
- }
-
@Override
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
@Nullable String[] args) {
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
index e965f55..8c529c4 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
@@ -18,7 +18,6 @@
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_ENABLED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED;
-import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_LOCATION_ENABLED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_SET_GEO_DETECTION_ENABLED;
import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_SUGGEST_GEO_LOCATION_TIME_ZONE;
@@ -57,8 +56,6 @@
return runSetAutoDetectionEnabled();
case SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED:
return runIsGeoDetectionSupported();
- case SHELL_COMMAND_IS_LOCATION_ENABLED:
- return runIsLocationEnabled();
case SHELL_COMMAND_IS_GEO_DETECTION_ENABLED:
return runIsGeoDetectionEnabled();
case SHELL_COMMAND_SET_GEO_DETECTION_ENABLED:
@@ -92,14 +89,6 @@
return 0;
}
- private int runIsLocationEnabled() {
- final PrintWriter pw = getOutPrintWriter();
- int userId = UserHandle.USER_CURRENT;
- boolean enabled = mInterface.isLocationEnabled(userId);
- pw.println(enabled);
- return 0;
- }
-
private int runIsGeoDetectionEnabled() {
final PrintWriter pw = getOutPrintWriter();
int userId = UserHandle.USER_CURRENT;
@@ -176,9 +165,6 @@
pw.printf(" %s\n", SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED);
pw.println(" Prints true/false according to whether geolocation time zone detection is"
+ " supported on this device");
- pw.printf(" %s\n", SHELL_COMMAND_IS_LOCATION_ENABLED);
- pw.println(" Prints true/false according to whether the master location toggle is"
- + " enabled for the current user");
pw.printf(" %s\n", SHELL_COMMAND_IS_GEO_DETECTION_ENABLED);
pw.println(" Prints true/false according to the geolocation tz detection setting");
pw.printf(" %s true|false\n", SHELL_COMMAND_SET_GEO_DETECTION_ENABLED);
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 4614355..5f6fff1 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -149,7 +149,7 @@
}
long expiration = SystemClock.elapsedRealtime() + duration;
mAlarmPendingIntent = PendingIntent.getBroadcast(mContext, 0, mAlarmIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, expiration,
mAlarmPendingIntent);
}
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index 42f12eb..0772503 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -51,7 +51,8 @@
public interface Callback {
void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs);
void onDeviceUnavailable(int deviceId);
- void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs);
+ void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs,
+ int cableConnectionStatus);
void onFirstFrameCaptured(int deviceId, int streamId);
}
@@ -142,8 +143,9 @@
mHandler.obtainMessage(EVENT_DEVICE_UNAVAILABLE, deviceId, 0).sendToTarget();
}
- private void streamConfigsChangedFromNative(int deviceId) {
- mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0).sendToTarget();
+ private void streamConfigsChangedFromNative(int deviceId, int cableConnectionStatus) {
+ mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId,
+ cableConnectionStatus).sendToTarget();
}
private void firstFrameCapturedFromNative(int deviceId, int streamId) {
@@ -184,6 +186,7 @@
case EVENT_STREAM_CONFIGURATION_CHANGED: {
TvStreamConfig[] configs;
int deviceId = msg.arg1;
+ int cableConnectionStatus = msg.arg2;
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "EVENT_STREAM_CONFIGURATION_CHANGED: deviceId = " + deviceId);
@@ -191,7 +194,7 @@
retrieveStreamConfigsLocked(deviceId);
configs = mStreamConfigs.get(deviceId);
}
- mCallback.onStreamConfigurationChanged(deviceId, configs);
+ mCallback.onStreamConfigurationChanged(deviceId, configs, cableConnectionStatus);
break;
}
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 2314afc..38ae51f 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -156,6 +156,7 @@
synchronized (mLock) {
Connection connection = new Connection(info);
connection.updateConfigsLocked(configs);
+ connection.updateCableConnectionStatusLocked(info.getCableConnectionStatus());
mConnections.put(info.getDeviceId(), connection);
buildHardwareListLocked();
mHandler.obtainMessage(
@@ -202,7 +203,8 @@
}
@Override
- public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs) {
+ public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs,
+ int cableConnectionStatus) {
synchronized (mLock) {
Connection connection = mConnections.get(deviceId);
if (connection == null) {
@@ -211,12 +213,22 @@
return;
}
int previousConfigsLength = connection.getConfigsLengthLocked();
+ int previousCableConnectionStatus = connection.getInputStateLocked();
connection.updateConfigsLocked(configs);
String inputId = mHardwareInputIdMap.get(deviceId);
- if (inputId != null
- && (previousConfigsLength == 0) != (connection.getConfigsLengthLocked() == 0)) {
- mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
- connection.getInputStateLocked(), 0, inputId).sendToTarget();
+ if (inputId != null) {
+ if (connection.updateCableConnectionStatusLocked(cableConnectionStatus)) {
+ if (previousCableConnectionStatus != connection.getInputStateLocked()) {
+ mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
+ connection.getInputStateLocked(), 0, inputId).sendToTarget();
+ }
+ } else {
+ if ((previousConfigsLength == 0)
+ != (connection.getConfigsLengthLocked() == 0)) {
+ mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
+ connection.getInputStateLocked(), 0, inputId).sendToTarget();
+ }
+ }
}
ITvInputHardwareCallback callback = connection.getCallbackLocked();
if (callback != null) {
@@ -380,8 +392,9 @@
return null;
}
- ResourceClientProfile profile =
- new ResourceClientProfile(tvInputSessionId, priorityHint);
+ ResourceClientProfile profile = new ResourceClientProfile();
+ profile.tvInputSessionId = tvInputSessionId;
+ profile.useCase = priorityHint;
ResourceClientProfile holderProfile = connection.getResourceClientProfileLocked();
if (holderProfile != null && trm != null
&& !trm.isHigherPriority(profile, holderProfile)) {
@@ -624,7 +637,7 @@
}
private class Connection implements IBinder.DeathRecipient {
- private final TvInputHardwareInfo mHardwareInfo;
+ private TvInputHardwareInfo mHardwareInfo;
private TvInputInfo mInfo;
private TvInputHardwareImpl mHardware = null;
private ITvInputHardwareCallback mCallback;
@@ -633,6 +646,7 @@
private Integer mResolvedUserId = null;
private Runnable mOnFirstFrameCaptured;
private ResourceClientProfile mResourceClientProfile = null;
+ private boolean mIsCableConnectionStatusUpdated = false;
public Connection(TvInputHardwareInfo hardwareInfo) {
mHardwareInfo = hardwareInfo;
@@ -735,6 +749,17 @@
+ " }";
}
+ public boolean updateCableConnectionStatusLocked(int cableConnectionStatus) {
+ // Update connection status only if it's not default value
+ if (cableConnectionStatus != TvInputHardwareInfo.CABLE_CONNECTION_STATUS_UNKNOWN
+ || mIsCableConnectionStatusUpdated) {
+ mIsCableConnectionStatusUpdated = true;
+ mHardwareInfo = mHardwareInfo.toBuilder()
+ .cableConnectionStatus(cableConnectionStatus).build();
+ }
+ return mIsCableConnectionStatusUpdated;
+ }
+
private int getConfigsLengthLocked() {
return mConfigs == null ? 0 : mConfigs.length;
}
@@ -742,7 +767,9 @@
private int getInputStateLocked() {
int configsLength = getConfigsLengthLocked();
if (configsLength > 0) {
- return INPUT_STATE_CONNECTED;
+ if (!mIsCableConnectionStatusUpdated) {
+ return INPUT_STATE_CONNECTED;
+ }
}
switch (mHardwareInfo.getCableConnectionStatus()) {
case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_CONNECTED:
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index ff5b65b..a1d2f8a 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1874,6 +1874,46 @@
}
@Override
+ public void pauseRecording(IBinder sessionToken, @NonNull Bundle params, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "pauseRecording");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ getSessionLocked(sessionToken, callingUid, resolvedUserId)
+ .pauseRecording(params);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slog.e(TAG, "error in pauseRecording", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void resumeRecording(IBinder sessionToken, @NonNull Bundle params, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+ userId, "resumeRecording");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ getSessionLocked(sessionToken, callingUid, resolvedUserId)
+ .resumeRecording(params);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slog.e(TAG, "error in resumeRecording", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public List<TvInputHardwareInfo> getHardwareList() throws RemoteException {
if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java
index 54ad1d2..4a81c95 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/CasResource.java
@@ -25,7 +25,7 @@
*
* @hide
*/
-public final class CasResource {
+public class CasResource {
private final int mSystemId;
@@ -38,7 +38,7 @@
*/
private Map<Integer, Integer> mOwnerClientIdsToSessionNum = new HashMap<>();
- private CasResource(Builder builder) {
+ CasResource(Builder builder) {
this.mSystemId = builder.mSystemId;
this.mMaxSessionNum = builder.mMaxSessionNum;
this.mAvailableSessionNum = builder.mMaxSessionNum;
@@ -111,7 +111,7 @@
public static class Builder {
private int mSystemId;
- private int mMaxSessionNum;
+ protected int mMaxSessionNum;
Builder(int systemId) {
this.mSystemId = systemId;
@@ -138,7 +138,7 @@
}
}
- private String ownersMapToString() {
+ protected String ownersMapToString() {
StringBuilder string = new StringBuilder("{");
for (int clienId : mOwnerClientIdsToSessionNum.keySet()) {
string.append(" clientId=")
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/CiCamResource.java b/services/core/java/com/android/server/tv/tunerresourcemanager/CiCamResource.java
new file mode 100644
index 0000000..31149f3
--- /dev/null
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/CiCamResource.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.tv.tunerresourcemanager;
+
+/**
+ * A CiCam resource object used by the Tuner Resource Manager to record the CiCam
+ * information.
+ *
+ * @hide
+ */
+public final class CiCamResource extends CasResource {
+ private CiCamResource(Builder builder) {
+ super(builder);
+ }
+
+ @Override
+ public String toString() {
+ return "CiCamResource[systemId=" + this.getSystemId()
+ + ", isFullyUsed=" + (this.isFullyUsed())
+ + ", maxSessionNum=" + this.getMaxSessionNum()
+ + ", ownerClients=" + ownersMapToString() + "]";
+ }
+
+ public int getCiCamId() {
+ return this.getSystemId();
+ }
+
+ /**
+ * Builder class for {@link CiCamResource}.
+ */
+ public static class Builder extends CasResource.Builder {
+ Builder(int systemId) {
+ super(systemId);
+ }
+
+ /**
+ * Builder for {@link CasResource}.
+ *
+ * @param maxSessionNum the max session num the current Cas has.
+ */
+ public Builder maxSessionNum(int maxSessionNum) {
+ super.mMaxSessionNum = maxSessionNum;
+ return this;
+ }
+
+ /**
+ * Build a {@link CiCamResource}.
+ *
+ * @return {@link CiCamResource}.
+ */
+ @Override
+ public CiCamResource build() {
+ CiCamResource ciCam = new CiCamResource(this);
+ return ciCam;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
index edf007d..5723e1d 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/ClientProfile.java
@@ -50,6 +50,8 @@
*/
private final int mProcessId;
+ private boolean mIsForeground;
+
/**
* All the clients that share the same resource would be under the same group id.
*
@@ -83,6 +85,11 @@
private int mUsingCasSystemId = INVALID_RESOURCE_ID;
/**
+ * CiCam id that is used by the client.
+ */
+ private int mUsingCiCamId = INVALID_RESOURCE_ID;
+
+ /**
* Optional arbitrary priority value given by the client.
*
* <p>This value can override the default priorotiy calculated from
@@ -113,6 +120,20 @@
return mProcessId;
}
+ /**
+ * Set the current isForeground status.
+ */
+ public void setForeground(boolean isForeground) {
+ mIsForeground = isForeground;
+ }
+
+ /**
+ * Get the previous recorded isForeground status.
+ */
+ public boolean isForeground() {
+ return mIsForeground;
+ }
+
public int getGroupId() {
return mGroupId;
}
@@ -222,6 +243,26 @@
}
/**
+ * Set when the client starts to connect to a CiCam.
+ *
+ * @param ciCamId ciCam being used.
+ */
+ public void useCiCam(int ciCamId) {
+ mUsingCiCamId = ciCamId;
+ }
+
+ public int getInUseCiCamId() {
+ return mUsingCiCamId;
+ }
+
+ /**
+ * Called when the client disconnect to a CiCam.
+ */
+ public void releaseCiCam() {
+ mUsingCiCamId = INVALID_RESOURCE_ID;
+ }
+
+ /**
* Called to reclaim all the resources being used by the current client.
*/
public void reclaimAllResources() {
@@ -229,6 +270,7 @@
mShareFeClientIds.clear();
mUsingLnbHandles.clear();
mUsingCasSystemId = INVALID_RESOURCE_ID;
+ mUsingCiCamId = INVALID_RESOURCE_ID;
}
@Override
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index 8c6e690..988582d 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -23,13 +23,14 @@
import android.content.Context;
import android.media.IResourceManagerService;
import android.media.tv.TvInputManager;
+import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ITunerResourceManager;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
-import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
@@ -71,6 +72,8 @@
private Map<Integer, LnbResource> mLnbResources = new HashMap<>();
// Map of the current available Cas resources
private Map<Integer, CasResource> mCasResources = new HashMap<>();
+ // Map of the current available CiCam resources
+ private Map<Integer, CiCamResource> mCiCamResources = new HashMap<>();
@GuardedBy("mLock")
private Map<Integer, ResourcesReclaimListenerRecord> mListeners = new HashMap<>();
@@ -141,8 +144,8 @@
throw new RemoteException("IResourcesReclaimListener can't be null!");
}
- if (!mPriorityCongfig.isDefinedUseCase(profile.getUseCase())) {
- throw new RemoteException("Use undefined client use case:" + profile.getUseCase());
+ if (!mPriorityCongfig.isDefinedUseCase(profile.useCase)) {
+ throw new RemoteException("Use undefined client use case:" + profile.useCase);
}
synchronized (mLock) {
@@ -209,14 +212,14 @@
throw new RemoteException("frontendHandle can't be null");
}
synchronized (mLock) {
- if (!checkClientExists(request.getClientId())) {
+ if (!checkClientExists(request.clientId)) {
throw new RemoteException("Request frontend from unregistered client: "
- + request.getClientId());
+ + request.clientId);
}
// If the request client is holding or sharing a frontend, throw an exception.
- if (!getClientProfile(request.getClientId()).getInUseFrontendHandles().isEmpty()) {
+ if (!getClientProfile(request.clientId).getInUseFrontendHandles().isEmpty()) {
throw new RemoteException("Release frontend before requesting another one. "
- + "Client id: " + request.getClientId());
+ + "Client id: " + request.clientId);
}
return requestFrontendInternal(request, frontendHandle);
}
@@ -252,9 +255,9 @@
throw new RemoteException("demuxHandle can't be null");
}
synchronized (mLock) {
- if (!checkClientExists(request.getClientId())) {
+ if (!checkClientExists(request.clientId)) {
throw new RemoteException("Request demux from unregistered client:"
- + request.getClientId());
+ + request.clientId);
}
return requestDemuxInternal(request, demuxHandle);
}
@@ -269,9 +272,9 @@
throw new RemoteException("descramblerHandle can't be null");
}
synchronized (mLock) {
- if (!checkClientExists(request.getClientId())) {
+ if (!checkClientExists(request.clientId)) {
throw new RemoteException("Request descrambler from unregistered client:"
- + request.getClientId());
+ + request.clientId);
}
return requestDescramblerInternal(request, descramblerHandle);
}
@@ -285,15 +288,31 @@
throw new RemoteException("casSessionHandle can't be null");
}
synchronized (mLock) {
- if (!checkClientExists(request.getClientId())) {
+ if (!checkClientExists(request.clientId)) {
throw new RemoteException("Request cas from unregistered client:"
- + request.getClientId());
+ + request.clientId);
}
return requestCasSessionInternal(request, casSessionHandle);
}
}
@Override
+ public boolean requestCiCam(@NonNull TunerCiCamRequest request,
+ @NonNull int[] ciCamHandle) throws RemoteException {
+ enforceTrmAccessPermission("requestCiCam");
+ if (ciCamHandle == null) {
+ throw new RemoteException("ciCamHandle can't be null");
+ }
+ synchronized (mLock) {
+ if (!checkClientExists(request.clientId)) {
+ throw new RemoteException("Request ciCam from unregistered client:"
+ + request.clientId);
+ }
+ return requestCiCamInternal(request, ciCamHandle);
+ }
+ }
+
+ @Override
public boolean requestLnb(@NonNull TunerLnbRequest request, @NonNull int[] lnbHandle)
throws RemoteException {
enforceTunerAccessPermission("requestLnb");
@@ -302,9 +321,9 @@
throw new RemoteException("lnbHandle can't be null");
}
synchronized (mLock) {
- if (!checkClientExists(request.getClientId())) {
+ if (!checkClientExists(request.clientId)) {
throw new RemoteException("Request lnb from unregistered client:"
- + request.getClientId());
+ + request.clientId);
}
return requestLnbInternal(request, lnbHandle);
}
@@ -378,6 +397,34 @@
}
@Override
+ public void releaseCiCam(int ciCamHandle, int clientId) throws RemoteException {
+ enforceTrmAccessPermission("releaseCiCam");
+ if (!validateResourceHandle(
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCamHandle)) {
+ throw new RemoteException("ciCamHandle can't be invalid");
+ }
+ synchronized (mLock) {
+ if (!checkClientExists(clientId)) {
+ throw new RemoteException("Release ciCam from unregistered client:" + clientId);
+ }
+ int ciCamId = getClientProfile(clientId).getInUseCiCamId();
+ if (ciCamId != getResourceIdFromHandle(ciCamHandle)) {
+ throw new RemoteException("The client " + clientId + " is not the owner of "
+ + "the releasing ciCam.");
+ }
+ CiCamResource ciCam = getCiCamResource(ciCamId);
+ if (ciCam == null) {
+ throw new RemoteException("Releasing ciCam does not exist.");
+ }
+ if (!ciCam.getOwnerClientIds().contains(clientId)) {
+ throw new RemoteException(
+ "Client is not the current owner of the releasing ciCam.");
+ }
+ releaseCiCamInternal(ciCam, clientId);
+ }
+ }
+
+ @Override
public void releaseLnb(int lnbHandle, int clientId) throws RemoteException {
enforceTunerAccessPermission("releaseLnb");
enforceTrmAccessPermission("releaseLnb");
@@ -441,12 +488,12 @@
// TODO tell if the client already exists
clientId[0] = mNextUnusedClientId++;
- int pid = profile.getTvInputSessionId() == null
+ int pid = profile.tvInputSessionId == null
? Binder.getCallingPid() /*callingPid*/
- : mTvInputManager.getClientPid(profile.getTvInputSessionId()); /*tvAppId*/
+ : mTvInputManager.getClientPid(profile.tvInputSessionId); /*tvAppId*/
// Update Media Resource Manager with the tvAppId
- if (profile.getTvInputSessionId() != null && mMediaResourceManager != null) {
+ if (profile.tvInputSessionId != null && mMediaResourceManager != null) {
try {
mMediaResourceManager.overridePid(Binder.getCallingPid(), pid);
} catch (RemoteException e) {
@@ -456,11 +503,13 @@
}
ClientProfile clientProfile = new ClientProfile.Builder(clientId[0])
- .tvInputSessionId(profile.getTvInputSessionId())
- .useCase(profile.getUseCase())
+ .tvInputSessionId(profile.tvInputSessionId)
+ .useCase(profile.useCase)
.processId(pid)
.build();
- clientProfile.setPriority(getClientPriority(profile.getUseCase(), pid));
+ clientProfile.setForeground(checkIsForeground(pid));
+ clientProfile.setPriority(
+ getClientPriority(profile.useCase, clientProfile.isForeground()));
addClientProfile(clientId[0], clientProfile, listener);
}
@@ -498,6 +547,7 @@
return false;
}
+ profile.setForeground(checkIsForeground(profile.getProcessId()));
profile.setPriority(priority);
profile.setNiceValue(niceValue);
@@ -520,16 +570,16 @@
// Update frontendResources map and other mappings accordingly
for (int i = 0; i < infos.length; i++) {
- if (getFrontendResource(infos[i].getHandle()) != null) {
+ if (getFrontendResource(infos[i].handle) != null) {
if (DEBUG) {
- Slog.d(TAG, "Frontend handle=" + infos[i].getHandle() + "exists.");
+ Slog.d(TAG, "Frontend handle=" + infos[i].handle + "exists.");
}
- updatingFrontendHandles.remove(infos[i].getHandle());
+ updatingFrontendHandles.remove(infos[i].handle);
} else {
// Add a new fe resource
- FrontendResource newFe = new FrontendResource.Builder(infos[i].getHandle())
- .type(infos[i].getFrontendType())
- .exclusiveGroupId(infos[i].getExclusiveGroupId())
+ FrontendResource newFe = new FrontendResource.Builder(infos[i].handle)
+ .type(infos[i].type)
+ .exclusiveGroupId(infos[i].exclusiveGroupId)
.build();
addFrontendResource(newFe);
}
@@ -583,24 +633,33 @@
// If maxSessionNum is 0, removing the Cas Resource.
if (maxSessionNum == 0) {
removeCasResource(casSystemId);
+ removeCiCamResource(casSystemId);
return;
}
// If the Cas exists, updates the Cas Resource accordingly.
CasResource cas = getCasResource(casSystemId);
+ CiCamResource ciCam = getCiCamResource(casSystemId);
if (cas != null) {
if (cas.getUsedSessionNum() > maxSessionNum) {
// Sort and release the short number of Cas resources.
int releasingCasResourceNum = cas.getUsedSessionNum() - maxSessionNum;
- releaseLowerPriorityClientCasResources(releasingCasResourceNum);
+ // TODO: handle CiCam session update.
}
cas.updateMaxSessionNum(maxSessionNum);
+ if (ciCam != null) {
+ ciCam.updateMaxSessionNum(maxSessionNum);
+ }
return;
}
// Add the new Cas Resource.
cas = new CasResource.Builder(casSystemId)
.maxSessionNum(maxSessionNum)
.build();
+ ciCam = new CiCamResource.Builder(casSystemId)
+ .maxSessionNum(maxSessionNum)
+ .build();
addCasResource(cas);
+ addCiCamResource(ciCam);
}
@VisibleForTesting
@@ -610,13 +669,17 @@
}
frontendHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE;
- ClientProfile requestClient = getClientProfile(request.getClientId());
+ ClientProfile requestClient = getClientProfile(request.clientId);
+ if (requestClient == null) {
+ return false;
+ }
+ clientPriorityUpdateOnRequest(requestClient);
int grantingFrontendHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
int inUseLowestPriorityFrHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
// Priority max value is 1000
int currentLowestPriority = MAX_CLIENT_PRIORITY + 1;
for (FrontendResource fr : getFrontendResources().values()) {
- if (fr.getType() == request.getFrontendType()) {
+ if (fr.getType() == request.frontendType) {
if (!fr.isInUse()) {
// Grant unused frontend with no exclusive group members first.
if (fr.getExclusiveGroupMemberFeHandles().isEmpty()) {
@@ -643,7 +706,7 @@
// Grant frontend when there is unused resource.
if (grantingFrontendHandle != TunerResourceManager.INVALID_RESOURCE_HANDLE) {
frontendHandle[0] = grantingFrontendHandle;
- updateFrontendClientMappingOnNewGrant(grantingFrontendHandle, request.getClientId());
+ updateFrontendClientMappingOnNewGrant(grantingFrontendHandle, request.clientId);
return true;
}
@@ -658,7 +721,7 @@
}
frontendHandle[0] = inUseLowestPriorityFrHandle;
updateFrontendClientMappingOnNewGrant(
- inUseLowestPriorityFrHandle, request.getClientId());
+ inUseLowestPriorityFrHandle, request.clientId);
return true;
}
@@ -683,7 +746,8 @@
}
lnbHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE;
- ClientProfile requestClient = getClientProfile(request.getClientId());
+ ClientProfile requestClient = getClientProfile(request.clientId);
+ clientPriorityUpdateOnRequest(requestClient);
int grantingLnbHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
int inUseLowestPriorityLnbHandle = TunerResourceManager.INVALID_RESOURCE_HANDLE;
// Priority max value is 1000
@@ -707,7 +771,7 @@
// Grant Lnb when there is unused resource.
if (grantingLnbHandle > -1) {
lnbHandle[0] = grantingLnbHandle;
- updateLnbClientMappingOnNewGrant(grantingLnbHandle, request.getClientId());
+ updateLnbClientMappingOnNewGrant(grantingLnbHandle, request.clientId);
return true;
}
@@ -720,7 +784,7 @@
return false;
}
lnbHandle[0] = inUseLowestPriorityLnbHandle;
- updateLnbClientMappingOnNewGrant(inUseLowestPriorityLnbHandle, request.getClientId());
+ updateLnbClientMappingOnNewGrant(inUseLowestPriorityLnbHandle, request.clientId);
return true;
}
@@ -732,23 +796,24 @@
if (DEBUG) {
Slog.d(TAG, "requestCasSession(request=" + request + ")");
}
- CasResource cas = getCasResource(request.getCasSystemId());
+ CasResource cas = getCasResource(request.casSystemId);
// Unregistered Cas System is treated as having unlimited sessions.
if (cas == null) {
- cas = new CasResource.Builder(request.getCasSystemId())
+ cas = new CasResource.Builder(request.casSystemId)
.maxSessionNum(Integer.MAX_VALUE)
.build();
addCasResource(cas);
}
casSessionHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE;
- ClientProfile requestClient = getClientProfile(request.getClientId());
+ ClientProfile requestClient = getClientProfile(request.clientId);
+ clientPriorityUpdateOnRequest(requestClient);
int lowestPriorityOwnerId = -1;
// Priority max value is 1000
int currentLowestPriority = MAX_CLIENT_PRIORITY + 1;
if (!cas.isFullyUsed()) {
casSessionHandle[0] = generateResourceHandle(
TunerResourceManager.TUNER_RESOURCE_TYPE_CAS_SESSION, cas.getSystemId());
- updateCasClientMappingOnNewGrant(request.getCasSystemId(), request.getClientId());
+ updateCasClientMappingOnNewGrant(request.casSystemId, request.clientId);
return true;
}
for (int ownerId : cas.getOwnerClientIds()) {
@@ -769,7 +834,56 @@
}
casSessionHandle[0] = generateResourceHandle(
TunerResourceManager.TUNER_RESOURCE_TYPE_CAS_SESSION, cas.getSystemId());
- updateCasClientMappingOnNewGrant(request.getCasSystemId(), request.getClientId());
+ updateCasClientMappingOnNewGrant(request.casSystemId, request.clientId);
+ return true;
+ }
+ return false;
+ }
+
+ @VisibleForTesting
+ protected boolean requestCiCamInternal(TunerCiCamRequest request, int[] ciCamHandle) {
+ if (DEBUG) {
+ Slog.d(TAG, "requestCiCamInternal(TunerCiCamRequest=" + request + ")");
+ }
+ CiCamResource ciCam = getCiCamResource(request.ciCamId);
+ // Unregistered Cas System is treated as having unlimited sessions.
+ if (ciCam == null) {
+ ciCam = new CiCamResource.Builder(request.ciCamId)
+ .maxSessionNum(Integer.MAX_VALUE)
+ .build();
+ addCiCamResource(ciCam);
+ }
+ ciCamHandle[0] = TunerResourceManager.INVALID_RESOURCE_HANDLE;
+ ClientProfile requestClient = getClientProfile(request.clientId);
+ clientPriorityUpdateOnRequest(requestClient);
+ int lowestPriorityOwnerId = -1;
+ // Priority max value is 1000
+ int currentLowestPriority = MAX_CLIENT_PRIORITY + 1;
+ if (!ciCam.isFullyUsed()) {
+ ciCamHandle[0] = generateResourceHandle(
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCam.getCiCamId());
+ updateCiCamClientMappingOnNewGrant(request.ciCamId, request.clientId);
+ return true;
+ }
+ for (int ownerId : ciCam.getOwnerClientIds()) {
+ // Record the client id with lowest priority that is using the current Cas system.
+ int priority = getOwnerClientPriority(ownerId);
+ if (currentLowestPriority > priority) {
+ lowestPriorityOwnerId = ownerId;
+ currentLowestPriority = priority;
+ }
+ }
+
+ // When all the CiCam sessions are occupied, reclaim the lowest priority client if the
+ // request client has higher priority.
+ if (lowestPriorityOwnerId > -1 && (requestClient.getPriority() > currentLowestPriority)) {
+ if (!reclaimResource(lowestPriorityOwnerId,
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM)) {
+ return false;
+ }
+ ciCamHandle[0] = generateResourceHandle(
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM, ciCam.getCiCamId());
+ updateCiCamClientMappingOnNewGrant(request.ciCamId, request.clientId);
return true;
}
return false;
@@ -790,15 +904,16 @@
return true;
}
- int challengerPid = challengerProfile.getTvInputSessionId() == null
+ int challengerPid = challengerProfile.tvInputSessionId == null
? Binder.getCallingPid() /*callingPid*/
- : mTvInputManager.getClientPid(challengerProfile.getTvInputSessionId()); /*tvAppId*/
- int holderPid = holderProfile.getTvInputSessionId() == null
+ : mTvInputManager.getClientPid(challengerProfile.tvInputSessionId); /*tvAppId*/
+ int holderPid = holderProfile.tvInputSessionId == null
? Binder.getCallingPid() /*callingPid*/
- : mTvInputManager.getClientPid(holderProfile.getTvInputSessionId()); /*tvAppId*/
+ : mTvInputManager.getClientPid(holderProfile.tvInputSessionId); /*tvAppId*/
- int challengerPriority = getClientPriority(challengerProfile.getUseCase(), challengerPid);
- int holderPriority = getClientPriority(holderProfile.getUseCase(), holderPid);
+ int challengerPriority = getClientPriority(
+ challengerProfile.useCase, checkIsForeground(challengerPid));
+ int holderPriority = getClientPriority(holderProfile.useCase, checkIsForeground(holderPid));
return challengerPriority > holderPriority;
}
@@ -833,6 +948,14 @@
}
@VisibleForTesting
+ protected void releaseCiCamInternal(CiCamResource ciCam, int ownerClientId) {
+ if (DEBUG) {
+ Slog.d(TAG, "releaseCiCamInternal(ciCamId=" + ciCam.getCiCamId() + ")");
+ }
+ updateCiCamClientMappingOnRelease(ciCam, ownerClientId);
+ }
+
+ @VisibleForTesting
protected boolean requestDemuxInternal(TunerDemuxRequest request, int[] demuxHandle) {
if (DEBUG) {
Slog.d(TAG, "requestDemux(request=" + request + ")");
@@ -843,6 +966,21 @@
}
@VisibleForTesting
+ // This mothod is to sync up the request client's foreground/background status and update
+ // the client priority accordingly whenever new resource request comes in.
+ protected void clientPriorityUpdateOnRequest(ClientProfile requestProfile) {
+ int pid = requestProfile.getProcessId();
+ boolean currentIsForeground = checkIsForeground(pid);
+ if (requestProfile.isForeground() == currentIsForeground) {
+ // To avoid overriding the priority set through updateClientPriority API.
+ return;
+ }
+ requestProfile.setForeground(currentIsForeground);
+ requestProfile.setPriority(
+ getClientPriority(requestProfile.getUseCase(), currentIsForeground));
+ }
+
+ @VisibleForTesting
protected boolean requestDescramblerInternal(
TunerDescramblerRequest request, int[] descramblerHandle) {
if (DEBUG) {
@@ -933,20 +1071,20 @@
}
@VisibleForTesting
- protected int getClientPriority(int useCase, int pid) {
+ protected int getClientPriority(int useCase, boolean isForeground) {
if (DEBUG) {
Slog.d(TAG, "getClientPriority useCase=" + useCase
- + ", pid=" + pid + ")");
+ + ", isForeground=" + isForeground + ")");
}
- if (isForeground(pid)) {
+ if (isForeground) {
return mPriorityCongfig.getForegroundPriority(useCase);
}
return mPriorityCongfig.getBackgroundPriority(useCase);
}
@VisibleForTesting
- protected boolean isForeground(int pid) {
+ protected boolean checkIsForeground(int pid) {
if (mActivityManager == null) {
return false;
}
@@ -994,6 +1132,13 @@
ownerProfile.useCas(grantingId);
}
+ private void updateCiCamClientMappingOnNewGrant(int grantingId, int ownerClientId) {
+ CiCamResource grantingCiCam = getCiCamResource(grantingId);
+ ClientProfile ownerProfile = getClientProfile(ownerClientId);
+ grantingCiCam.setOwner(ownerClientId);
+ ownerProfile.useCiCam(grantingId);
+ }
+
private void updateCasClientMappingOnRelease(
@NonNull CasResource releasingCas, int ownerClientId) {
ClientProfile ownerProfile = getClientProfile(ownerClientId);
@@ -1001,6 +1146,13 @@
ownerProfile.releaseCas();
}
+ private void updateCiCamClientMappingOnRelease(
+ @NonNull CiCamResource releasingCiCam, int ownerClientId) {
+ ClientProfile ownerProfile = getClientProfile(ownerClientId);
+ releasingCiCam.removeOwner(ownerClientId);
+ ownerProfile.releaseCiCam();
+ }
+
/**
* Get the owner client's priority.
*
@@ -1093,15 +1245,31 @@
}
@VisibleForTesting
+ @Nullable
+ protected CiCamResource getCiCamResource(int ciCamId) {
+ return mCiCamResources.get(ciCamId);
+ }
+
+ @VisibleForTesting
protected Map<Integer, CasResource> getCasResources() {
return mCasResources;
}
+ @VisibleForTesting
+ protected Map<Integer, CiCamResource> getCiCamResources() {
+ return mCiCamResources;
+ }
+
private void addCasResource(CasResource newCas) {
// Update resource list and available id list
mCasResources.put(newCas.getSystemId(), newCas);
}
+ private void addCiCamResource(CiCamResource newCiCam) {
+ // Update resource list and available id list
+ mCiCamResources.put(newCiCam.getCiCamId(), newCiCam);
+ }
+
private void removeCasResource(int removingId) {
CasResource cas = getCasResource(removingId);
if (cas == null) {
@@ -1113,6 +1281,17 @@
mCasResources.remove(removingId);
}
+ private void removeCiCamResource(int removingId) {
+ CiCamResource ciCam = getCiCamResource(removingId);
+ if (ciCam == null) {
+ return;
+ }
+ for (int ownerId : ciCam.getOwnerClientIds()) {
+ getClientProfile(ownerId).releaseCiCam();
+ }
+ mCiCamResources.remove(removingId);
+ }
+
private void releaseLowerPriorityClientCasResources(int releasingCasResourceNum) {
// TODO: Sort with a treemap
@@ -1161,6 +1340,10 @@
if (profile.getInUseCasSystemId() != ClientProfile.INVALID_RESOURCE_ID) {
getCasResource(profile.getInUseCasSystemId()).removeOwner(profile.getId());
}
+ // Clear CiCam
+ if (profile.getInUseCiCamId() != ClientProfile.INVALID_RESOURCE_ID) {
+ getCiCamResource(profile.getInUseCiCamId()).removeOwner(profile.getId());
+ }
// Clear Frontend
clearFrontendAndClientMapping(profile);
profile.reclaimAllResources();
diff --git a/services/core/java/com/android/server/utils/ManagedApplicationService.java b/services/core/java/com/android/server/utils/ManagedApplicationService.java
index c555388..c103e0e 100644
--- a/services/core/java/com/android/server/utils/ManagedApplicationService.java
+++ b/services/core/java/com/android/server/utils/ManagedApplicationService.java
@@ -304,7 +304,7 @@
}
if (mSettingsAction != null) {
intent.putExtra(Intent.EXTRA_CLIENT_INTENT,
- PendingIntent.getActivity(mContext, 0, new Intent(mSettingsAction), 0));
+ PendingIntent.getActivity(mContext, 0, new Intent(mSettingsAction), PendingIntent.FLAG_MUTABLE_UNAUDITED));
}
mConnection = new ServiceConnection() {
diff --git a/services/core/java/com/android/server/utils/WatchableImpl.java b/services/core/java/com/android/server/utils/WatchableImpl.java
index 527db54..8a04ccf 100644
--- a/services/core/java/com/android/server/utils/WatchableImpl.java
+++ b/services/core/java/com/android/server/utils/WatchableImpl.java
@@ -122,7 +122,7 @@
/**
* Return the sealed state.
*/
- public boolean isFrozen() {
+ public boolean isSealed() {
synchronized (mObservers) {
return mSealed;
}
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 7ea8e04..7024e67 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -16,33 +16,438 @@
package com.android.server.vcn;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+
+import static com.android.server.VcnManagementService.VDBG;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.net.ConnectivityManager;
+import android.net.InetAddresses;
+import android.net.IpPrefix;
+import android.net.IpSecManager;
+import android.net.IpSecManager.IpSecTunnelInterface;
+import android.net.IpSecManager.ResourceUnavailableException;
+import android.net.IpSecTransform;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
+import android.net.annotations.PolicyDirection;
+import android.net.ipsec.ike.ChildSessionCallback;
+import android.net.ipsec.ike.ChildSessionConfiguration;
+import android.net.ipsec.ike.ChildSessionParams;
+import android.net.ipsec.ike.IkeSession;
+import android.net.ipsec.ike.IkeSessionCallback;
+import android.net.ipsec.ike.IkeSessionConfiguration;
+import android.net.ipsec.ike.IkeSessionParams;
+import android.net.ipsec.ike.exceptions.IkeException;
+import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.vcn.VcnGatewayConnectionConfig;
import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Message;
import android.os.ParcelUuid;
+import android.telephony.TelephonyManager;
+import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
/**
* A single VCN Gateway Connection, providing a single public-facing VCN network.
*
* <p>This class handles mobility events, performs retries, and tracks safe-mode conditions.
*
+ * <pre>Internal state transitions are as follows:
+ *
+ * +----------------------------+ +------------------------------+
+ * | DisconnectedState | Teardown or | DisconnectingState |
+ * | |<--no available--| |
+ * | Initial state. | underlying | Transitive state for tearing |
+ * +----------------------------+ networks | tearing down an IKE session. |
+ * | +------------------------------+
+ * | ^ |
+ * Underlying Network Teardown requested | Not tearing down
+ * changed +--or retriable error--+ and has available
+ * | | occurred underlying network
+ * | ^ |
+ * v | v
+ * +----------------------------+ | +------------------------------+
+ * | ConnectingState |<----------------| RetryTimeoutState |
+ * | | | | |
+ * | Transitive state for | | | Transitive state for |
+ * | starting IKE negotiation. |---+ | handling retriable errors. |
+ * +----------------------------+ | +------------------------------+
+ * | |
+ * IKE session |
+ * negotiated |
+ * | |
+ * v |
+ * +----------------------------+ ^
+ * | ConnectedState | |
+ * | | |
+ * | Stable state where | |
+ * | gateway connection is set | |
+ * | up, and Android Network is | |
+ * | connected. |---+
+ * +----------------------------+
+ * </pre>
+ *
* @hide
*/
-public class VcnGatewayConnection extends Handler implements UnderlyingNetworkTrackerCallback {
+public class VcnGatewayConnection extends StateMachine {
private static final String TAG = VcnGatewayConnection.class.getSimpleName();
+ private static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0");
+ private static final int ARG_NOT_PRESENT = Integer.MIN_VALUE;
+
+ private static final String DISCONNECT_REASON_INTERNAL_ERROR = "Uncaught exception: ";
+ private static final String DISCONNECT_REASON_UNDERLYING_NETWORK_LOST =
+ "Underlying Network lost";
+ private static final String DISCONNECT_REASON_TEARDOWN = "teardown() called on VcnTunnel";
+ private static final int TOKEN_ANY = Integer.MIN_VALUE;
+
+ private static final int NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS = 30;
+ private static final int TEARDOWN_TIMEOUT_SECONDS = 5;
+
+ private interface EventInfo {}
+
+ /**
+ * Sent when there are changes to the underlying network (per the UnderlyingNetworkTracker).
+ *
+ * <p>May indicate an entirely new underlying network, OR a change in network properties.
+ *
+ * <p>Relevant in ALL states.
+ *
+ * <p>In the Connected state, this MAY indicate a mobility even occurred.
+ *
+ * @param arg1 The "any" token; this event is always applicable.
+ * @param obj @NonNull An EventUnderlyingNetworkChangedInfo instance with relevant data.
+ */
+ private static final int EVENT_UNDERLYING_NETWORK_CHANGED = 1;
+
+ private static class EventUnderlyingNetworkChangedInfo implements EventInfo {
+ @Nullable public final UnderlyingNetworkRecord newUnderlying;
+
+ EventUnderlyingNetworkChangedInfo(@Nullable UnderlyingNetworkRecord newUnderlying) {
+ this.newUnderlying = newUnderlying;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(newUnderlying);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof EventUnderlyingNetworkChangedInfo)) {
+ return false;
+ }
+
+ final EventUnderlyingNetworkChangedInfo rhs = (EventUnderlyingNetworkChangedInfo) other;
+ return Objects.equals(newUnderlying, rhs.newUnderlying);
+ }
+ }
+
+ /**
+ * Sent (delayed) to trigger an attempt to reestablish the tunnel.
+ *
+ * <p>Only relevant in the Retry-timeout state, discarded in all other states.
+ *
+ * <p>Upon receipt of this signal, the state machine will transition from the Retry-timeout
+ * state to the Connecting state.
+ *
+ * @param arg1 The "any" token; no sessions are active in the RetryTimeoutState.
+ */
+ private static final int EVENT_RETRY_TIMEOUT_EXPIRED = 2;
+
+ /**
+ * Sent when a gateway connection has been lost, either due to a IKE or child failure.
+ *
+ * <p>Relevant in all states that have an IKE session.
+ *
+ * <p>Upon receipt of this signal, the state machine will (unless loss of the session is
+ * expected) transition to the Disconnecting state, to ensure IKE session closure before
+ * retrying, or fully shutting down.
+ *
+ * @param arg1 The session token for the IKE Session that was lost, used to prevent out-of-date
+ * signals from propagating.
+ * @param obj @NonNull An EventSessionLostInfo instance with relevant data.
+ */
+ private static final int EVENT_SESSION_LOST = 3;
+
+ private static class EventSessionLostInfo implements EventInfo {
+ @Nullable public final Exception exception;
+
+ EventSessionLostInfo(@NonNull Exception exception) {
+ this.exception = exception;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(exception);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof EventSessionLostInfo)) {
+ return false;
+ }
+
+ final EventSessionLostInfo rhs = (EventSessionLostInfo) other;
+ return Objects.equals(exception, rhs.exception);
+ }
+ }
+
+ /**
+ * Sent when an IKE session has completely closed.
+ *
+ * <p>Relevant only in the Disconnecting State, used to identify that a session being torn down
+ * was fully closed. If this event is not fired within a timely fashion, the IKE session will be
+ * forcibly terminated.
+ *
+ * <p>Upon receipt of this signal, the state machine will (unless closure of the session is
+ * expected) transition to the Disconnected or RetryTimeout states, depending on whether the
+ * GatewayConnection is being fully torn down.
+ *
+ * @param arg1 The session token for the IKE Session that was lost, used to prevent out-of-date
+ * signals from propagating.
+ * @param obj @NonNull An EventSessionLostInfo instance with relevant data.
+ */
+ private static final int EVENT_SESSION_CLOSED = 4;
+
+ /**
+ * Sent when an IKE Child Transform was created, and should be applied to the tunnel.
+ *
+ * <p>Only relevant in the Connecting, Connected and Migrating states. This callback MUST be
+ * handled in the Connected or Migrating states, and should be deferred if necessary.
+ *
+ * @param arg1 The session token for the IKE Session that had a new child created, used to
+ * prevent out-of-date signals from propagating.
+ * @param obj @NonNull An EventTransformCreatedInfo instance with relevant data.
+ */
+ private static final int EVENT_TRANSFORM_CREATED = 5;
+
+ private static class EventTransformCreatedInfo implements EventInfo {
+ @PolicyDirection public final int direction;
+ @NonNull public final IpSecTransform transform;
+
+ EventTransformCreatedInfo(
+ @PolicyDirection int direction, @NonNull IpSecTransform transform) {
+ this.direction = direction;
+ this.transform = Objects.requireNonNull(transform);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(direction, transform);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof EventTransformCreatedInfo)) {
+ return false;
+ }
+
+ final EventTransformCreatedInfo rhs = (EventTransformCreatedInfo) other;
+ return direction == rhs.direction && Objects.equals(transform, rhs.transform);
+ }
+ }
+
+ /**
+ * Sent when an IKE Child Session was completely opened and configured successfully.
+ *
+ * <p>Only relevant in the Connected and Migrating states.
+ *
+ * @param arg1 The session token for the IKE Session for which a child was opened and configured
+ * successfully, used to prevent out-of-date signals from propagating.
+ * @param obj @NonNull An EventSetupCompletedInfo instance with relevant data.
+ */
+ private static final int EVENT_SETUP_COMPLETED = 6;
+
+ private static class EventSetupCompletedInfo implements EventInfo {
+ @NonNull public final ChildSessionConfiguration childSessionConfig;
+
+ EventSetupCompletedInfo(@NonNull ChildSessionConfiguration childSessionConfig) {
+ this.childSessionConfig = Objects.requireNonNull(childSessionConfig);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(childSessionConfig);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof EventSetupCompletedInfo)) {
+ return false;
+ }
+
+ final EventSetupCompletedInfo rhs = (EventSetupCompletedInfo) other;
+ return Objects.equals(childSessionConfig, rhs.childSessionConfig);
+ }
+ }
+
+ /**
+ * Sent when conditions (internal or external) require a disconnect.
+ *
+ * <p>Relevant in all states except the Disconnected state.
+ *
+ * <p>This signal is often fired with a timeout in order to prevent disconnecting during
+ * transient conditions, such as network switches. Upon the transient passing, the signal is
+ * canceled based on the disconnect reason.
+ *
+ * <p>Upon receipt of this signal, the state machine MUST tear down all active sessions, cancel
+ * any pending work items, and move to the Disconnected state.
+ *
+ * @param arg1 The "any" token; this signal is always honored.
+ * @param obj @NonNull An EventDisconnectRequestedInfo instance with relevant data.
+ */
+ private static final int EVENT_DISCONNECT_REQUESTED = 7;
+
+ private static class EventDisconnectRequestedInfo implements EventInfo {
+ /** The reason why the disconnect was requested. */
+ @NonNull public final String reason;
+
+ EventDisconnectRequestedInfo(@NonNull String reason) {
+ this.reason = Objects.requireNonNull(reason);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(reason);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof EventDisconnectRequestedInfo)) {
+ return false;
+ }
+
+ final EventDisconnectRequestedInfo rhs = (EventDisconnectRequestedInfo) other;
+ return reason.equals(rhs.reason);
+ }
+ }
+
+ /**
+ * Sent (delayed) to trigger a forcible close of an IKE session.
+ *
+ * <p>Only relevant in the Disconnecting state, discarded in all other states.
+ *
+ * <p>Upon receipt of this signal, the state machine will transition from the Disconnecting
+ * state to the Disconnected state.
+ *
+ * @param arg1 The session token for the IKE Session that is being torn down, used to prevent
+ * out-of-date signals from propagating.
+ */
+ private static final int EVENT_TEARDOWN_TIMEOUT_EXPIRED = 8;
+
+ @NonNull private final DisconnectedState mDisconnectedState = new DisconnectedState();
+ @NonNull private final DisconnectingState mDisconnectingState = new DisconnectingState();
+ @NonNull private final ConnectingState mConnectingState = new ConnectingState();
+ @NonNull private final ConnectedState mConnectedState = new ConnectedState();
+ @NonNull private final RetryTimeoutState mRetryTimeoutState = new RetryTimeoutState();
+
@NonNull private final VcnContext mVcnContext;
@NonNull private final ParcelUuid mSubscriptionGroup;
@NonNull private final UnderlyingNetworkTracker mUnderlyingNetworkTracker;
@NonNull private final VcnGatewayConnectionConfig mConnectionConfig;
@NonNull private final Dependencies mDeps;
+ @NonNull private final VcnUnderlyingNetworkTrackerCallback mUnderlyingNetworkTrackerCallback;
+
+ @NonNull private final IpSecManager mIpSecManager;
+ @NonNull private final IpSecTunnelInterface mTunnelIface;
+
+ /** Running state of this VcnGatewayConnection. */
+ private boolean mIsRunning = true;
+
+ /**
+ * The token used by the primary/current/active session.
+ *
+ * <p>This token MUST be updated when a new stateful/async session becomes the
+ * primary/current/active session. Example cases where the session changes are:
+ *
+ * <ul>
+ * <li>Switching to an IKE session as the primary session
+ * </ul>
+ *
+ * <p>In the migrating state, where two sessions may be active, this value MUST represent the
+ * primary session. This is USUALLY the existing session, and is only switched to the new
+ * session when:
+ *
+ * <ul>
+ * <li>The new session connects successfully, and becomes the primary session
+ * <li>The existing session is lost, and the remaining (new) session becomes the primary
+ * session
+ * </ul>
+ */
+ private int mCurrentToken = -1;
+
+ /**
+ * The next usable token.
+ *
+ * <p>A new token MUST be used for all new IKE sessions.
+ */
+ private int mNextToken = 0;
+
+ /**
+ * The number of unsuccessful attempts since the last successful connection.
+ *
+ * <p>This number MUST be incremented each time the RetryTimeout state is entered, and cleared
+ * each time the Connected state is entered.
+ */
+ private int mFailedAttempts = 0;
+
+ /**
+ * The current underlying network.
+ *
+ * <p>Set in any states, always @NonNull in all states except Disconnected, null otherwise.
+ */
+ private UnderlyingNetworkRecord mUnderlying;
+
+ /**
+ * The active IKE session.
+ *
+ * <p>Set in Connecting or Migrating States, always @NonNull in Connecting, Connected, and
+ * Migrating states, null otherwise.
+ */
+ private IkeSession mIkeSession;
+
+ /**
+ * The last known child configuration.
+ *
+ * <p>Set in Connected and Migrating states, always @NonNull in Connected, Migrating
+ * states, @Nullable otherwise.
+ */
+ private ChildSessionConfiguration mChildConfig;
+
+ /**
+ * The active network agent.
+ *
+ * <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable
+ * otherwise.
+ */
+ private NetworkAgent mNetworkAgent;
+
public VcnGatewayConnection(
@NonNull VcnContext vcnContext,
@NonNull ParcelUuid subscriptionGroup,
@@ -55,30 +460,350 @@
@NonNull ParcelUuid subscriptionGroup,
@NonNull VcnGatewayConnectionConfig connectionConfig,
@NonNull Dependencies deps) {
- super(Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
+ super(TAG, Objects.requireNonNull(vcnContext, "Missing vcnContext").getLooper());
mVcnContext = vcnContext;
mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
mConnectionConfig = Objects.requireNonNull(connectionConfig, "Missing connectionConfig");
mDeps = Objects.requireNonNull(deps, "Missing deps");
+ mUnderlyingNetworkTrackerCallback = new VcnUnderlyingNetworkTrackerCallback();
+
mUnderlyingNetworkTracker =
- mDeps.newUnderlyingNetworkTracker(mVcnContext, subscriptionGroup, this);
+ mDeps.newUnderlyingNetworkTracker(
+ mVcnContext, subscriptionGroup, mUnderlyingNetworkTrackerCallback);
+ mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class);
+
+ IpSecTunnelInterface iface;
+ try {
+ iface =
+ mIpSecManager.createIpSecTunnelInterface(
+ DUMMY_ADDR, DUMMY_ADDR, new Network(-1));
+ } catch (IOException | ResourceUnavailableException e) {
+ teardownAsynchronously();
+ mTunnelIface = null;
+
+ return;
+ }
+
+ mTunnelIface = iface;
+
+ addState(mDisconnectedState);
+ addState(mDisconnectingState);
+ addState(mConnectingState);
+ addState(mConnectedState);
+ addState(mRetryTimeoutState);
+
+ setInitialState(mDisconnectedState);
+ setDbg(VDBG);
+ start();
}
- /** Asynchronously tears down this GatewayConnection, and any resources used */
+ /**
+ * Asynchronously tears down this GatewayConnection, and any resources used.
+ *
+ * <p>Once torn down, this VcnTunnel CANNOT be started again.
+ */
public void teardownAsynchronously() {
mUnderlyingNetworkTracker.teardown();
+
+ // No need to call setInterfaceDown(); the IpSecInterface is being fully torn down.
+ if (mTunnelIface != null) {
+ mTunnelIface.close();
+ }
+
+ sendMessage(
+ EVENT_DISCONNECT_REQUESTED,
+ TOKEN_ANY,
+ new EventDisconnectRequestedInfo(DISCONNECT_REASON_TEARDOWN));
+ quit();
+
+ // TODO: Notify VcnInstance (via callbacks) of permanent teardown of this tunnel, since this
+ // is also called asynchronously when a NetworkAgent becomes unwanted
}
- private static class Dependencies {
+ private class VcnUnderlyingNetworkTrackerCallback implements UnderlyingNetworkTrackerCallback {
+ @Override
+ public void onSelectedUnderlyingNetworkChanged(
+ @Nullable UnderlyingNetworkRecord underlying) {
+ // If underlying is null, all underlying networks have been lost. Disconnect VCN after a
+ // timeout.
+ if (underlying == null) {
+ sendMessageDelayed(
+ EVENT_DISCONNECT_REQUESTED,
+ TOKEN_ANY,
+ new EventDisconnectRequestedInfo(DISCONNECT_REASON_UNDERLYING_NETWORK_LOST),
+ TimeUnit.SECONDS.toMillis(NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS));
+ return;
+ }
+
+ // Cancel any existing disconnect due to loss of underlying network
+ // getHandler() can return null if the state machine has already quit. Since this is
+ // called
+ // from other classes, this condition must be verified.
+ if (getHandler() != null) {
+ getHandler()
+ .removeEqualMessages(
+ EVENT_DISCONNECT_REQUESTED,
+ new EventDisconnectRequestedInfo(
+ DISCONNECT_REASON_UNDERLYING_NETWORK_LOST));
+ }
+ sendMessage(
+ EVENT_UNDERLYING_NETWORK_CHANGED,
+ TOKEN_ANY,
+ new EventUnderlyingNetworkChangedInfo(underlying));
+ }
+ }
+
+ private void sendMessage(int what, int token, EventInfo data) {
+ super.sendMessage(what, token, ARG_NOT_PRESENT, data);
+ }
+
+ private void sendMessage(int what, int token, int arg2, EventInfo data) {
+ super.sendMessage(what, token, arg2, data);
+ }
+
+ private void sendMessageDelayed(int what, int token, EventInfo data, long timeout) {
+ super.sendMessageDelayed(what, token, ARG_NOT_PRESENT, data, timeout);
+ }
+
+ private void sendMessageDelayed(int what, int token, int arg2, EventInfo data, long timeout) {
+ super.sendMessageDelayed(what, token, arg2, data, timeout);
+ }
+
+ private void sessionLost(int token, @Nullable Exception exception) {
+ sendMessage(EVENT_SESSION_LOST, token, new EventSessionLostInfo(exception));
+ }
+
+ private void sessionClosed(int token, @Nullable Exception exception) {
+ // SESSION_LOST MUST be sent before SESSION_CLOSED to ensure that the SM moves to the
+ // Disconnecting state.
+ sessionLost(token, exception);
+ sendMessage(EVENT_SESSION_CLOSED, token);
+ }
+
+ private void childTransformCreated(
+ int token, @NonNull IpSecTransform transform, int direction) {
+ sendMessage(
+ EVENT_TRANSFORM_CREATED,
+ token,
+ new EventTransformCreatedInfo(direction, transform));
+ }
+
+ private void childOpened(int token, @NonNull ChildSessionConfiguration childConfig) {
+ sendMessage(EVENT_SETUP_COMPLETED, token, new EventSetupCompletedInfo(childConfig));
+ }
+
+ private abstract class BaseState extends State {
+ protected void enterState() throws Exception {}
+
+ protected abstract void processStateMsg(Message msg) throws Exception;
+ }
+ /**
+ * State representing the a disconnected VCN tunnel.
+ *
+ * <p>This is also is the initial state.
+ */
+ private class DisconnectedState extends BaseState {
+ @Override
+ protected void processStateMsg(Message msg) {}
+ }
+
+ private abstract class ActiveBaseState extends BaseState {}
+
+ /**
+ * Transitive state representing a VCN that is tearing down an IKE session.
+ *
+ * <p>In this state, the IKE session is in the process of being torn down. If the IKE session
+ * does not complete teardown in a timely fashion, it will be killed (forcibly closed).
+ */
+ private class DisconnectingState extends ActiveBaseState {
+ @Override
+ protected void processStateMsg(Message msg) {}
+ }
+
+ /**
+ * Transitive state representing a VCN that is making an primary (non-handover) connection.
+ *
+ * <p>This state starts IKE negotiation, but defers transform application & network setup to the
+ * Connected state.
+ */
+ private class ConnectingState extends ActiveBaseState {
+ @Override
+ protected void processStateMsg(Message msg) {}
+ }
+
+ private abstract class ConnectedStateBase extends ActiveBaseState {}
+
+ /**
+ * Stable state representing a VCN that has a functioning connection to the mobility anchor.
+ *
+ * <p>This state handles IPsec transform application (initial and rekey), NetworkAgent setup,
+ * and monitors for mobility events.
+ */
+ class ConnectedState extends ConnectedStateBase {
+ @Override
+ protected void processStateMsg(Message msg) {}
+ }
+
+ /**
+ * Transitive state representing a VCN that failed to establish a connection, and will retry.
+ *
+ * <p>This state will be exited upon a new underlying network being found, or timeout expiry.
+ */
+ class RetryTimeoutState extends ActiveBaseState {
+ @Override
+ protected void processStateMsg(Message msg) {}
+ }
+
+ // TODO: Remove this when migrating to new NetworkAgent API
+ private static NetworkInfo buildNetworkInfo(boolean isConnected) {
+ NetworkInfo info =
+ new NetworkInfo(
+ ConnectivityManager.TYPE_MOBILE,
+ TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ "MOBILE",
+ "VCN");
+ info.setDetailedState(
+ isConnected ? DetailedState.CONNECTED : DetailedState.DISCONNECTED, null, null);
+
+ return info;
+ }
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static NetworkCapabilities buildNetworkCapabilities(
+ @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
+ final NetworkCapabilities caps = new NetworkCapabilities();
+
+ caps.addTransportType(TRANSPORT_CELLULAR);
+ caps.addCapability(NET_CAPABILITY_NOT_CONGESTED);
+ caps.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+
+ // Add exposed capabilities
+ for (int cap : gatewayConnectionConfig.getAllExposedCapabilities()) {
+ caps.addCapability(cap);
+ }
+
+ return caps;
+ }
+
+ private static LinkProperties buildConnectedLinkProperties(
+ @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig,
+ @NonNull IpSecTunnelInterface tunnelIface,
+ @NonNull ChildSessionConfiguration childConfig) {
+ final LinkProperties lp = new LinkProperties();
+
+ lp.setInterfaceName(tunnelIface.getInterfaceName());
+ for (LinkAddress addr : childConfig.getInternalAddresses()) {
+ lp.addLinkAddress(addr);
+ }
+ for (InetAddress addr : childConfig.getInternalDnsServers()) {
+ lp.addDnsServer(addr);
+ }
+
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
+
+ lp.setMtu(gatewayConnectionConfig.getMaxMtu());
+
+ return lp;
+ }
+
+ private class IkeSessionCallbackImpl implements IkeSessionCallback {
+ private final int mToken;
+
+ IkeSessionCallbackImpl(int token) {
+ mToken = token;
+ }
+
+ @Override
+ public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) {
+ Slog.v(TAG, "IkeOpened for token " + mToken);
+ // Nothing to do here.
+ }
+
+ @Override
+ public void onClosed() {
+ Slog.v(TAG, "IkeClosed for token " + mToken);
+ sessionClosed(mToken, null);
+ }
+
+ @Override
+ public void onClosedExceptionally(@NonNull IkeException exception) {
+ Slog.v(TAG, "IkeClosedExceptionally for token " + mToken, exception);
+ sessionClosed(mToken, exception);
+ }
+
+ @Override
+ public void onError(@NonNull IkeProtocolException exception) {
+ Slog.v(TAG, "IkeError for token " + mToken, exception);
+ // Non-fatal, log and continue.
+ }
+ }
+
+ private class ChildSessionCallbackImpl implements ChildSessionCallback {
+ private final int mToken;
+
+ ChildSessionCallbackImpl(int token) {
+ mToken = token;
+ }
+
+ @Override
+ public void onOpened(@NonNull ChildSessionConfiguration childConfig) {
+ Slog.v(TAG, "ChildOpened for token " + mToken);
+ childOpened(mToken, childConfig);
+ }
+
+ @Override
+ public void onClosed() {
+ Slog.v(TAG, "ChildClosed for token " + mToken);
+ sessionLost(mToken, null);
+ }
+
+ @Override
+ public void onClosedExceptionally(@NonNull IkeException exception) {
+ Slog.v(TAG, "ChildClosedExceptionally for token " + mToken, exception);
+ sessionLost(mToken, exception);
+ }
+
+ @Override
+ public void onIpSecTransformCreated(@NonNull IpSecTransform transform, int direction) {
+ Slog.v(TAG, "ChildTransformCreated; Direction: " + direction + "; token " + mToken);
+ childTransformCreated(mToken, transform, direction);
+ }
+
+ @Override
+ public void onIpSecTransformDeleted(@NonNull IpSecTransform transform, int direction) {
+ // Nothing to be done; no references to the IpSecTransform are held, and this transform
+ // will be closed by the IKE library.
+ Slog.v(TAG, "ChildTransformDeleted; Direction: " + direction + "; for token " + mToken);
+ }
+ }
+
+ /** External dependencies used by VcnGatewayConnection, for injection in tests. */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static class Dependencies {
+ /** Builds a new UnderlyingNetworkTracker. */
public UnderlyingNetworkTracker newUnderlyingNetworkTracker(
VcnContext vcnContext,
ParcelUuid subscriptionGroup,
UnderlyingNetworkTrackerCallback callback) {
return new UnderlyingNetworkTracker(vcnContext, subscriptionGroup, callback);
}
- }
- @Override
- public void onSelectedUnderlyingNetworkChanged(@Nullable UnderlyingNetworkRecord underlying) {}
+ /** Builds a new IkeSession. */
+ public IkeSession newIkeSession(
+ VcnContext vcnContext,
+ IkeSessionParams ikeSessionParams,
+ ChildSessionParams childSessionParams,
+ IkeSessionCallback ikeSessionCallback,
+ ChildSessionCallback childSessionCallback) {
+ return new IkeSession(
+ vcnContext.getContext(),
+ ikeSessionParams,
+ childSessionParams,
+ new HandlerExecutor(new Handler(vcnContext.getLooper())),
+ ikeSessionCallback,
+ childSessionCallback);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index a34a507..536375f 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -36,6 +36,7 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import java.util.ArrayList;
@@ -59,7 +60,8 @@
private final Vibrator mVibrator;
private final AudioManager mAudioManager;
private final SettingsObserver mSettingObserver;
- private final UidObserver mUidObserver;
+ @VisibleForTesting
+ final UidObserver mUidObserver;
@GuardedBy("mLock")
private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
@@ -251,8 +253,7 @@
* allowed to play in the background (i.e. it's a notification, ringtone or alarm vibration).
*/
public boolean shouldVibrateForUid(int uid, int usageHint) {
- return mUidObserver.isUidForeground(uid) || isNotification(usageHint)
- || isRingtone(usageHint) || isAlarm(usageHint);
+ return mUidObserver.isUidForeground(uid) || isClassAlarm(usageHint);
}
/**
@@ -292,6 +293,11 @@
return usageHint == VibrationAttributes.USAGE_ALARM;
}
+ private static boolean isClassAlarm(int usageHint) {
+ return (usageHint & VibrationAttributes.USAGE_CLASS_MASK)
+ == VibrationAttributes.USAGE_CLASS_ALARM;
+ }
+
/** Updates all vibration settings and triggers registered listeners. */
public void updateSettings() {
synchronized (mLock) {
@@ -414,7 +420,8 @@
}
/** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */
- private final class UidObserver extends IUidObserver.Stub {
+ @VisibleForTesting
+ final class UidObserver extends IUidObserver.Stub {
private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();
public boolean isUidForeground(int uid) {
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 03cf021..6bca484 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -288,7 +288,7 @@
return;
}
mLastLaunchedActivity = r;
- if (!r.noDisplay) {
+ if (!r.noDisplay && !r.isReportedDrawn()) {
if (DEBUG_METRICS) Slog.i(TAG, "Add pending draw " + r);
mPendingDrawActivities.add(r);
}
@@ -576,7 +576,7 @@
+ " processSwitch=" + processSwitch + " info=" + info);
}
- if (launchedActivity.isReportedDrawn()) {
+ if (launchedActivity.isReportedDrawn() && launchedActivity.isVisible()) {
// Launched activity is already visible. We cannot measure windows drawn delay.
abort(info, "launched activity already visible");
return;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index a9c5474..aefd51f 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -294,6 +294,7 @@
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
+import android.window.IRemoteTransition;
import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
@@ -467,6 +468,7 @@
private ActivityOptions mPendingOptions;
/** Non-null if {@link #mPendingOptions} specifies the remote animation. */
private RemoteAnimationAdapter mPendingRemoteAnimation;
+ private IRemoteTransition mPendingRemoteTransition;
ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
@@ -894,6 +896,9 @@
pw.print("pendingRemoteAnimationCallingPid=");
pw.println(mPendingRemoteAnimation.getCallingPid());
}
+ if (mPendingRemoteTransition != null) {
+ pw.print(prefix + " pendingRemoteTransition=" + mPendingRemoteTransition);
+ }
if (appTimeTracker != null) {
appTimeTracker.dumpWithHeader(pw, prefix, false);
}
@@ -3884,6 +3889,7 @@
if (options.getAnimationType() == ANIM_REMOTE_ANIMATION) {
mPendingRemoteAnimation = options.getRemoteAnimationAdapter();
}
+ mPendingRemoteTransition = options.getRemoteTransition();
}
void applyOptionsAnimation() {
@@ -4064,6 +4070,7 @@
void clearOptionsAnimation() {
mPendingOptions = null;
mPendingRemoteAnimation = null;
+ mPendingRemoteTransition = null;
}
ActivityOptions getOptions() {
@@ -4078,6 +4085,12 @@
return opts;
}
+ IRemoteTransition takeRemoteTransition() {
+ IRemoteTransition out = mPendingRemoteTransition;
+ mPendingRemoteTransition = null;
+ return out;
+ }
+
boolean allowMoveToFront() {
return mPendingOptions == null || !mPendingOptions.getAvoidMoveToFront();
}
@@ -4773,7 +4786,7 @@
void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) {
// This activity is not currently visible, but is running. Tell it to become visible.
- if (mState == RESUMED || this == starting) {
+ if ((mState == RESUMED && mVisibleRequested) || this == starting) {
if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
"Not making visible, r=" + this + " state=" + mState + " starting=" + starting);
return;
@@ -6479,8 +6492,9 @@
mLastReportedConfiguration.setConfiguration(global, override);
}
- boolean hasCompatDisplayInsets() {
- return mCompatDisplayInsets != null;
+ @Nullable
+ CompatDisplayInsets getCompatDisplayInsets() {
+ return mCompatDisplayInsets;
}
/**
@@ -6569,7 +6583,12 @@
}
return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
// The configuration of non-standard type should be enforced by system.
- && isActivityTypeStandard()
+ // {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} is set when this activity is
+ // added to a task, but this function is called when resolving the launch params, at
+ // which point, the activity type is still undefined if it will be standard.
+ // For other non-standard types, the type is set in the constructor, so this should
+ // not be a problem.
+ && isActivityTypeStandardOrUndefined()
&& !mAtmService.mForceResizableActivities;
}
@@ -7798,13 +7817,16 @@
/**
* The precomputed insets of the display in each rotation. This is used to make the size
* compatibility mode activity compute the configuration without relying on its current display.
- * This currently only supports fullscreen and freeform windowing mode.
*/
static class CompatDisplayInsets {
+ /** The container width on rotation 0. */
private final int mWidth;
+ /** The container height on rotation 0. */
private final int mHeight;
+ /** Whether the {@link Task} windowingMode represents a floating window*/
final boolean mIsFloating;
-
+ /** Whether the {@link Task} is letterboxed when the unresizable activity is first shown. */
+ final boolean mIsTaskLetterboxed;
/**
* The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
* is used to compute the appBounds.
@@ -7831,27 +7853,24 @@
mNonDecorInsets[rotation] = emptyRect;
mStableInsets[rotation] = emptyRect;
}
+ mIsTaskLetterboxed = false;
return;
}
final Task task = container.getTask();
- if (task != null && task.isTaskLetterboxed()) {
- // For apps in Task letterbox, it should fill the task bounds.
- final Point dimensions = getRotationZeroDimensions(task);
- mWidth = dimensions.x;
- mHeight = dimensions.y;
- } else {
- // If the activity is not floating nor letterboxed, assume it fills the root.
- final RootDisplayArea root = container.getRootDisplayArea();
- if (root == null || root == display) {
- mWidth = display.mBaseDisplayWidth;
- mHeight = display.mBaseDisplayHeight;
- } else {
- final Point dimensions = getRotationZeroDimensions(root);
- mWidth = dimensions.x;
- mHeight = dimensions.y;
- }
- }
+ mIsTaskLetterboxed = task != null && task.isTaskLetterboxed();
+
+ // Store the bounds of the Task for the non-resizable activity to use in size compat
+ // mode so that the activity will not be resized regardless the windowing mode it is
+ // currently in.
+ final WindowContainer filledContainer = task != null ? task : display;
+ final Point dimensions = getRotationZeroDimensions(filledContainer);
+ mWidth = dimensions.x;
+ mHeight = dimensions.y;
+
+ // Bounds of the filled container if it doesn't fill the display.
+ final Rect unfilledContainerBounds =
+ filledContainer.getBounds().equals(display.getBounds()) ? null : new Rect();
final DisplayPolicy policy = display.getDisplayPolicy();
for (int rotation = 0; rotation < 4; rotation++) {
mNonDecorInsets[rotation] = new Rect();
@@ -7864,6 +7883,20 @@
policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
mStableInsets[rotation].set(mNonDecorInsets[rotation]);
policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
+
+ if (unfilledContainerBounds == null) {
+ continue;
+ }
+ // The insets is based on the display, but the container may be smaller than the
+ // display, so update the insets to exclude parts that are not intersected with the
+ // container.
+ unfilledContainerBounds.set(filledContainer.getBounds());
+ display.rotateBounds(
+ filledContainer.getConfiguration().windowConfiguration.getRotation(),
+ rotation,
+ unfilledContainerBounds);
+ updateInsetsForBounds(unfilledContainerBounds, dw, dh, mNonDecorInsets[rotation]);
+ updateInsetsForBounds(unfilledContainerBounds, dw, dh, mStableInsets[rotation]);
}
}
@@ -7881,6 +7914,18 @@
return rotated ? new Point(height, width) : new Point(width, height);
}
+ /**
+ * Updates the display insets to exclude the parts that are not intersected with the given
+ * bounds.
+ */
+ private static void updateInsetsForBounds(Rect bounds, int displayWidth, int displayHeight,
+ Rect inset) {
+ inset.left = Math.max(0, inset.left - bounds.left);
+ inset.top = Math.max(0, inset.top - bounds.top);
+ inset.right = Math.max(0, bounds.right - displayWidth + inset.right);
+ inset.bottom = Math.max(0, bounds.bottom - displayHeight + inset.bottom);
+ }
+
void getBoundsByRotation(Rect outBounds, int rotation) {
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
final int dw = rotated ? mHeight : mWidth;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 7a4bcb1..e67210e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -110,6 +110,7 @@
import android.util.DebugUtils;
import android.util.Pools.SynchronizedPool;
import android.util.Slog;
+import android.window.IRemoteTransition;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.HeavyWeightSwitcherActivity;
@@ -118,6 +119,7 @@
import com.android.server.am.PendingIntentRecord;
import com.android.server.pm.InstantAppResolver;
import com.android.server.power.ShutdownCheckPoints;
+import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
import com.android.server.wm.ActivityTaskSupervisor.PendingActivityLaunch;
@@ -1572,6 +1574,10 @@
final Transition newTransition = (!mService.getTransitionController().isCollecting()
&& mService.getTransitionController().getTransitionPlayer() != null)
? mService.getTransitionController().createTransition(TRANSIT_OPEN) : null;
+ IRemoteTransition remoteTransition = r.takeRemoteTransition();
+ if (newTransition != null && remoteTransition != null) {
+ newTransition.setRemoteTransition(remoteTransition);
+ }
mService.getTransitionController().collect(r);
try {
mService.deferWindowLayout();
@@ -1589,6 +1595,20 @@
newTransition.abort();
}
} else {
+ if (!mAvoidMoveToFront && mDoResume
+ && mRootWindowContainer.hasVisibleWindowAboveNotificationShade(
+ r.launchedFromUid)) {
+ // If the UID launching the activity has a visible window on top of the
+ // notification shade and it's launching an activity that's going to be at the
+ // front, we should move the shade out of the way so the user can see it.
+ // We want to avoid the case where the activity is launched on top of a
+ // background task which is not moved to the front.
+ StatusBarManagerInternal statusBar = mService.getStatusBarManagerInternal();
+ if (statusBar != null) {
+ // This results in a async call since the interface is one-way
+ statusBar.collapsePanels();
+ }
+ }
if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
// The activity is started new rather than just brought forward, so record
// it as an existence change.
@@ -1596,7 +1616,7 @@
}
if (newTransition != null) {
mService.getTransitionController().requestStartTransition(newTransition,
- r.getTask());
+ mTargetTask, remoteTransition);
} else {
// Make the collecting transition wait until this request is ready.
mService.getTransitionController().setReady(false);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 109ea09..ecdef3f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -293,6 +293,11 @@
@Nullable String packageName);
/**
+ * Returns whether the app can close system dialogs or not.
+ */
+ public abstract boolean canCloseSystemDialogs(int pid, int uid);
+
+ /**
* Called after the voice interaction service has changed.
*/
public abstract void notifyActiveVoiceInteractionServiceChanged(ComponentName component);
@@ -380,15 +385,6 @@
}
}
- /**
- * Set the corresponding display information for the process global configuration. To be called
- * when we need to show IME on a different display.
- *
- * @param pid The process id associated with the IME window.
- * @param displayId The ID of the display showing the IME.
- */
- public abstract void onImeWindowSetOnDisplay(int pid, int displayId);
-
public abstract void sendActivityResult(int callingUid, IBinder activityToken,
String resultWho, int requestCode, int resultCode, Intent data);
public abstract void clearPendingResultForActivity(
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 039f22d..3c06488 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -28,6 +28,8 @@
import static android.Manifest.permission.REMOVE_TASKS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.STOP_APP_SWITCHES;
+import static android.app.ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS;
+import static android.app.ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
@@ -253,6 +255,7 @@
import com.android.server.inputmethod.InputMethodSystemProperty;
import com.android.server.pm.UserManagerService;
import com.android.server.policy.PermissionPolicyInternal;
+import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -342,6 +345,7 @@
/** The cached sys ui service component name from package manager. */
private ComponentName mSysUiServiceComponent;
private PermissionPolicyInternal mPermissionPolicyInternal;
+ private StatusBarManagerInternal mStatusBarManagerInternal;
@VisibleForTesting
final ActivityTaskManagerInternal mInternal;
PowerManagerInternal mPowerManagerInternal;
@@ -2927,14 +2931,12 @@
}
if (!canCloseSystemDialogs(pid, uid, process)) {
// The app can't close system dialogs, throw only if it targets S+
- if (CompatChanges.isChangeEnabled(
- ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, uid)) {
+ if (CompatChanges.isChangeEnabled(LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, uid)) {
throw new SecurityException(
"Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS
+ " broadcast from " + caller + " requires "
+ Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS + ".");
- } else if (CompatChanges.isChangeEnabled(
- ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS, uid)) {
+ } else if (CompatChanges.isChangeEnabled(DROP_CLOSE_SYSTEM_DIALOGS, uid)) {
Slog.e(TAG,
"Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS
+ " broadcast from " + caller + " requires "
@@ -2958,6 +2960,11 @@
== PERMISSION_GRANTED) {
return true;
}
+ if (process == null) {
+ synchronized (mGlobalLock) {
+ process = mProcessMap.getProcess(pid);
+ }
+ }
if (process != null) {
// Check if the instrumentation of the process has the permission. This covers the
// usual test started from the shell (which has the permission) case. This is needed
@@ -2978,6 +2985,20 @@
return true;
}
}
+ // This covers the case where the app is displaying some UI on top of the notification shade
+ // and wants to start an activity. The app then sends the intent in order to move the
+ // notification shade out of the way and show the activity to the user. This is fine since
+ // the caller already has privilege to show a visible window on top of the notification
+ // shade, so it can already prevent the user from accessing the shade if it wants to.
+ // We only allow for targetSdk < S, for S+ we automatically collapse the shade on
+ // startActivity() for these apps.
+ if (!CompatChanges.isChangeEnabled(LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, uid)) {
+ synchronized (mGlobalLock) {
+ if (mRootWindowContainer.hasVisibleWindowAboveNotificationShade(uid)) {
+ return true;
+ }
+ }
+ }
return false;
}
@@ -4782,6 +4803,13 @@
return mPermissionPolicyInternal;
}
+ StatusBarManagerInternal getStatusBarManagerInternal() {
+ if (mStatusBarManagerInternal == null) {
+ mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
+ }
+ return mStatusBarManagerInternal;
+ }
+
AppWarnings getAppWarningsLocked() {
return mAppWarnings;
}
@@ -4986,6 +5014,34 @@
}
}
+ /**
+ * Sets the corresponding {@link DisplayArea} information for the process global
+ * configuration. To be called when we need to show IME on a different {@link DisplayArea}
+ * or display.
+ *
+ * @param pid The process id associated with the IME window.
+ * @param imeContainer The DisplayArea that contains the IME window.
+ */
+ void onImeWindowSetOnDisplayArea(final int pid, @NonNull final DisplayArea imeContainer) {
+ // Don't update process-level configuration for Multi-Client IME process since other
+ // IMEs on other displays will also receive this configuration change due to IME
+ // services use the same application config/context.
+ if (InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED) return;
+
+ if (pid == MY_PID || pid < 0) {
+ ProtoLog.w(WM_DEBUG_CONFIGURATION,
+ "Trying to update display configuration for system/invalid process.");
+ return;
+ }
+ final WindowProcessController process = mProcessMap.getProcess(pid);
+ if (process == null) {
+ ProtoLog.w(WM_DEBUG_CONFIGURATION, "Trying to update display "
+ + "configuration for invalid process, pid=%d", pid);
+ return;
+ }
+ process.registerDisplayAreaConfigurationListener(imeContainer);
+ }
+
final class H extends Handler {
static final int REPORT_TIME_TRACKER_MSG = 1;
@@ -5237,6 +5293,12 @@
}
@Override
+ public boolean canCloseSystemDialogs(int pid, int uid) {
+ return ActivityTaskManagerService.this.canCloseSystemDialogs(pid, uid,
+ null /* process */);
+ }
+
+ @Override
public void notifyActiveVoiceInteractionServiceChanged(ComponentName component) {
synchronized (mGlobalLock) {
mActiveVoiceInteractionServiceComponent = component;
@@ -5483,44 +5545,6 @@
}
}
- /**
- * Set the corresponding display information for the process global configuration. To be
- * called when we need to show IME on a different display.
- *
- * @param pid The process id associated with the IME window.
- * @param displayId The ID of the display showing the IME.
- */
- @Override
- public void onImeWindowSetOnDisplay(final int pid, final int displayId) {
- // Don't update process-level configuration for Multi-Client IME process since other
- // IMEs on other displays will also receive this configuration change due to IME
- // services use the same application config/context.
- if (InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED) return;
-
- if (pid == MY_PID || pid < 0) {
- ProtoLog.w(WM_DEBUG_CONFIGURATION,
- "Trying to update display configuration for system/invalid process.");
- return;
- }
- synchronized (mGlobalLock) {
- final DisplayContent displayContent =
- mRootWindowContainer.getDisplayContent(displayId);
- if (displayContent == null) {
- // Call might come when display is not yet added or has been removed.
- ProtoLog.w(WM_DEBUG_CONFIGURATION, "Trying to update display "
- + "configuration for non-existing displayId=%d", displayId);
- return;
- }
- final WindowProcessController process = mProcessMap.getProcess(pid);
- if (process == null) {
- ProtoLog.w(WM_DEBUG_CONFIGURATION, "Trying to update display "
- + "configuration for invalid process, pid=%d", pid);
- return;
- }
- process.registerDisplayConfigurationListener(displayContent);
- }
- }
-
@Override
public void sendActivityResult(int callingUid, IBinder activityToken, String resultWho,
int requestCode, int resultCode, Intent data) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 599bf37..a68f5575 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1365,7 +1365,8 @@
mUserLeaving = true;
}
- mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_TO_FRONT, task);
+ mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_TO_FRONT,
+ 0 /* flags */, task, options != null ? options.getRemoteTransition() : null);
reason = reason + " findTaskToMoveToFront";
boolean reparented = false;
if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) {
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 1fd6d00..15483cb 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -564,22 +564,6 @@
}
@Override
- void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- super.onParentChanged(newParent, oldParent);
- if (mOrganizer != null || newParent == null) {
- return;
- }
- // Check if we have a registered organizer, just after mSurfaceControl is ready.
- setOrganizer(mOrganizerController.getOrganizerByFeature(mFeatureId));
- }
-
- @Override
- void removeImmediately() {
- setOrganizer(null);
- super.removeImmediately();
- }
-
- @Override
DisplayArea getDisplayArea() {
return this;
}
diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index 38f78c9..53f7009 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -21,7 +21,6 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.DisplayArea.Type.ANY;
-import android.annotation.Nullable;
import android.content.pm.ParceledListSlice;
import android.os.Binder;
import android.os.IBinder;
@@ -51,10 +50,6 @@
private final WindowManagerGlobalLock mGlobalLock;
private final HashMap<Integer, IDisplayAreaOrganizer> mOrganizersByFeatureIds = new HashMap();
- @Nullable IDisplayAreaOrganizer getOrganizerByFeature(int featureId) {
- return mOrganizersByFeatureIds.get(featureId);
- }
-
private class DeathRecipient implements IBinder.DeathRecipient {
int mFeature;
IDisplayAreaOrganizer mOrganizer;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4494d99..d4629d9 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -257,7 +257,7 @@
@Retention(RetentionPolicy.SOURCE)
@interface ForceScalingMode {}
- ActivityTaskManagerService mAtmService;
+ final ActivityTaskManagerService mAtmService;
/**
* Unique logical identifier of this display.
@@ -294,7 +294,7 @@
// window containers together and move them in-sync if/when needed. We use a subclass of
// WindowContainer which is omitted from screen magnification, as the IME is never magnified.
// TODO(display-area): is "no magnification" in the comment still true?
- private final ImeContainer mImeWindowsContainers = new ImeContainer(mWmService);
+ private final ImeContainer mImeWindowsContainer = new ImeContainer(mWmService);
@VisibleForTesting
final DisplayAreaPolicy mDisplayAreaPolicy;
@@ -1028,7 +1028,7 @@
// Setup the policy and build the display area hierarchy.
mDisplayAreaPolicy = mWmService.getDisplayAreaPolicyProvider().instantiate(
- mWmService, this /* content */, this /* root */, mImeWindowsContainers);
+ mWmService, this /* content */, this /* root */, mImeWindowsContainer);
final List<DisplayArea<? extends WindowContainer>> areas =
mDisplayAreaPolicy.getDisplayAreas(FEATURE_WINDOWED_MAGNIFICATION);
@@ -1125,7 +1125,7 @@
switch (token.windowType) {
case TYPE_INPUT_METHOD:
case TYPE_INPUT_METHOD_DIALOG:
- mImeWindowsContainers.addChild(token);
+ mImeWindowsContainer.addChild(token);
break;
default:
mDisplayAreaPolicy.addWindow(token);
@@ -2410,7 +2410,7 @@
}
boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
- return mImeWindowsContainers.forAllWindowForce(callback, traverseTopToBottom);
+ return mImeWindowsContainer.forAllWindowForce(callback, traverseTopToBottom);
}
/**
@@ -3024,7 +3024,7 @@
public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
super.dump(pw, prefix, dumpAll);
pw.print(prefix);
- pw.println("Display: mDisplayId=" + mDisplayId + " stacks=" + getRootTaskCount());
+ pw.println("Display: mDisplayId=" + mDisplayId + " rootTasks=" + getRootTaskCount());
final String subPrefix = " " + prefix;
pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
@@ -3107,30 +3107,31 @@
pw.println();
- // Dump stack references
- final Task homeStack = getDefaultTaskDisplayArea().getRootHomeTask();
- if (homeStack != null) {
- pw.println(prefix + "homeStack=" + homeStack.getName());
+ // Dump root task references
+ final Task rootHomeTask = getDefaultTaskDisplayArea().getRootHomeTask();
+ if (rootHomeTask != null) {
+ pw.println(prefix + "rootHomeTask=" + rootHomeTask.getName());
}
- final Task pinnedStack = getDefaultTaskDisplayArea().getRootPinnedTask();
- if (pinnedStack != null) {
- pw.println(prefix + "pinnedStack=" + pinnedStack.getName());
+ final Task rootPinnedTask = getDefaultTaskDisplayArea().getRootPinnedTask();
+ if (rootPinnedTask != null) {
+ pw.println(prefix + "rootPinnedTask=" + rootPinnedTask.getName());
}
- final Task splitScreenPrimaryStack = getDefaultTaskDisplayArea()
+ final Task rootSplitScreenPrimaryTask = getDefaultTaskDisplayArea()
.getRootSplitScreenPrimaryTask();
- if (splitScreenPrimaryStack != null) {
- pw.println(prefix + "splitScreenPrimaryStack=" + splitScreenPrimaryStack.getName());
+ if (rootSplitScreenPrimaryTask != null) {
+ pw.println(
+ prefix + "rootSplitScreenPrimaryTask=" + rootSplitScreenPrimaryTask.getName());
}
// TODO: Support recents on non-default task containers
- final Task recentsStack = getDefaultTaskDisplayArea().getRootTask(
+ final Task rootRecentsTask = getDefaultTaskDisplayArea().getRootTask(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
- if (recentsStack != null) {
- pw.println(prefix + "recentsStack=" + recentsStack.getName());
+ if (rootRecentsTask != null) {
+ pw.println(prefix + "rootRecentsTask=" + rootRecentsTask.getName());
}
- final Task dreamStack =
+ final Task rootDreamTask =
getRootTask(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_DREAM);
- if (dreamStack != null) {
- pw.println(prefix + "dreamStack=" + dreamStack.getName());
+ if (rootDreamTask != null) {
+ pw.println(prefix + "rootDreamTask=" + rootDreamTask.getName());
}
pw.println();
@@ -3150,7 +3151,7 @@
@Override
public String toString() {
- return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
+ return "Display " + mDisplayId + " info=" + mDisplayInfo + " rootTasks=" + mChildren;
}
String getName() {
@@ -3500,8 +3501,7 @@
// Update display configuration for IME process.
if (mInputMethodWindow != null) {
final int imePid = mInputMethodWindow.mSession.mPid;
- mWmService.mAtmInternal.onImeWindowSetOnDisplay(imePid,
- mInputMethodWindow.getDisplayId());
+ mAtmService.onImeWindowSetOnDisplayArea(imePid, mImeWindowsContainer);
}
mInsetsStateController.getSourceProvider(ITYPE_IME).setWindow(win,
mDisplayPolicy.getImeSourceFrameProvider(), null /* imeFrameProvider */);
@@ -3732,7 +3732,7 @@
if (targetRoot != null) {
// Reposition the IME container to the target root to get the correct bounds and
// config.
- targetRoot.placeImeContainer(mImeWindowsContainers);
+ targetRoot.placeImeContainer(mImeWindowsContainer);
}
}
// 2. Reparent the IME container surface to either the input target app, or the IME window
@@ -3783,7 +3783,7 @@
final SurfaceControl newParent = computeImeParent();
if (newParent != null && newParent != mInputMethodSurfaceParent) {
mInputMethodSurfaceParent = newParent;
- getPendingTransaction().reparent(mImeWindowsContainers.mSurfaceControl, newParent);
+ getPendingTransaction().reparent(mImeWindowsContainer.mSurfaceControl, newParent);
scheduleAnimation();
}
}
@@ -3820,7 +3820,7 @@
}
// Otherwise, we just attach it to where the display area policy put it.
- return mImeWindowsContainers.getParent().getSurfaceControl();
+ return mImeWindowsContainer.getParent().getSurfaceControl();
}
void setLayoutNeeded() {
@@ -4568,7 +4568,7 @@
@Override
void assignChildLayers(SurfaceControl.Transaction t) {
- mImeWindowsContainers.setNeedsLayer();
+ mImeWindowsContainer.setNeedsLayer();
final WindowState imeTarget = mImeLayeringTarget;
// In the case where we have an IME target that is not in split-screen mode IME
// assignment is easy. We just need the IME to go directly above the target. This way
@@ -4591,7 +4591,7 @@
!(imeTarget.inMultiWindowMode()
|| imeTarget.mToken.isAppTransitioning()) && (
imeTarget.getSurfaceControl() != null))) {
- mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
+ mImeWindowsContainer.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
// TODO: We need to use an extra level on the app surface to ensure
// this is always above SurfaceView but always below attached window.
1);
@@ -4599,7 +4599,7 @@
// The IME surface parent may not be its window parent's surface
// (@see #computeImeParent), so set relative layer here instead of letting the window
// parent to assign layer.
- mImeWindowsContainers.assignRelativeLayer(t, mInputMethodSurfaceParent, 1);
+ mImeWindowsContainer.assignRelativeLayer(t, mInputMethodSurfaceParent, 1);
}
super.assignChildLayers(t);
}
@@ -4614,8 +4614,8 @@
* with {@link WindowState#assignLayer}
*/
void assignRelativeLayerForImeTargetChild(SurfaceControl.Transaction t, WindowContainer child) {
- mImeWindowsContainers.setNeedsLayer();
- child.assignRelativeLayer(t, mImeWindowsContainers.getSurfaceControl(), 1);
+ mImeWindowsContainer.setNeedsLayer();
+ child.assignRelativeLayer(t, mImeWindowsContainer.getSurfaceControl(), 1);
}
@Override
@@ -4882,7 +4882,7 @@
}
DisplayArea.Tokens getImeContainer() {
- return mImeWindowsContainers;
+ return mImeWindowsContainer;
}
SurfaceControl getOverlayLayer() {
diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags
index 6c34609..40b80f7 100644
--- a/services/core/java/com/android/server/wm/EventLogTags.logtags
+++ b/services/core/java/com/android/server/wm/EventLogTags.logtags
@@ -35,22 +35,18 @@
30019 wm_relaunch_resume_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3)
# An activity has been relaunched:
30020 wm_relaunch_activity (User|1|5),(Token|1|5),(Task ID|1|5),(Component Name|3)
-# The activity's onPause has been called.
-30021 wm_on_paused_called (Token|1|5),(Component Name|3),(Reason|3)
-# The activity's onResume has been called.
-30022 wm_on_resume_called (Token|1|5),(Component Name|3),(Reason|3)
# Activity set to resumed
30043 wm_set_resumed_activity (User|1|5),(Component Name|3),(Reason|3)
-# Stack focus
-30044 wm_focused_stack (User|1|5),(Display Id|1|5),(Focused Stack Id|1|5),(Last Focused Stack Id|1|5),(Reason|3)
+# Root task focus
+30044 wm_focused_root_task (User|1|5),(Display Id|1|5),(Focused Root Task Id|1|5),(Last Focused Root Task Id|1|5),(Reason|3)
# Attempting to stop an activity
30048 wm_stop_activity (User|1|5),(Token|1|5),(Component Name|3)
-# The task is being removed from its parent stack
-30061 wm_remove_task (Task ID|1|5), (Stack ID|1|5)
+# The task is being removed from its parent task
+30061 wm_remove_task (Task ID|1|5), (Root Task ID|1|5)
# An activity been add into stopping list
30066 wm_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
@@ -61,17 +57,11 @@
# Out of memory for surfaces.
31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3)
# Task created.
-31001 wm_task_created (TaskId|1|5),(StackId|1|5)
+31001 wm_task_created (TaskId|1|5),(RootTaskId|1|5)
# Task moved to top (1) or bottom (0).
31002 wm_task_moved (TaskId|1|5),(ToTop|1),(Index|1)
# Task removed with source explanation.
31003 wm_task_removed (TaskId|1|5),(Reason|3)
-# Stack created.
-31004 wm_stack_created (StackId|1|5)
-# Home stack moved to top (1) or bottom (0).
-31005 wm_home_stack_moved (ToTop|1)
-# Stack removed.
-31006 wm_stack_removed (StackId|1|5)
# bootanim finished:
31007 wm_boot_animation_done (time|2|3)
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 54996a6..23acbf7 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -36,6 +36,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
import static android.view.WindowManager.TRANSIT_NONE;
@@ -3137,6 +3138,27 @@
});
}
+ /**
+ * Returns {@code true} if {@code uid} has a visible window that's above a window of type {@link
+ * WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}. If there is no window with type {@link
+ * WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}, it returns {@code false}.
+ */
+ boolean hasVisibleWindowAboveNotificationShade(int uid) {
+ boolean[] visibleWindowFound = {false};
+ // We only return true if we found the notification shade (ie. window of type
+ // TYPE_NOTIFICATION_SHADE). Usually, it should always be there, but if for some reason
+ // it isn't, we should better be on the safe side and return false for this.
+ return forAllWindows(w -> {
+ if (w.mOwnerUid == uid && w.isVisible()) {
+ visibleWindowFound[0] = true;
+ }
+ if (w.mAttrs.type == TYPE_NOTIFICATION_SHADE) {
+ return visibleWindowFound[0];
+ }
+ return false;
+ }, true /* traverseTopToBottom */);
+ }
+
private boolean shouldCloseAssistant(ActivityRecord r, String reason) {
if (!r.isActivityTypeAssistant()) return false;
if (reason == SYSTEM_DIALOG_REASON_ASSIST) return false;
@@ -3572,7 +3594,7 @@
public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
super.dump(pw, prefix, dumpAll);
pw.print(prefix);
- pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedRootTask());
+ pw.println("topDisplayFocusedRootTask=" + getTopDisplayFocusedRootTask());
for (int i = getChildCount() - 1; i >= 0; --i) {
final DisplayContent display = getChildAt(i);
display.dump(pw, prefix, dumpAll);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 0cefa95..ff2509b 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -21,6 +21,7 @@
import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY;
import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT;
@@ -104,6 +105,7 @@
// If non-system overlays from this process can be hidden by the user or app using
// HIDE_NON_SYSTEM_OVERLAY_WINDOWS.
final boolean mOverlaysCanBeHidden;
+ final boolean mCanCreateSystemApplicationOverlay;
final boolean mCanHideNonSystemOverlayWindows;
final boolean mCanAcquireSleepToken;
private AlertWindowNotification mAlertWindowNotification;
@@ -127,6 +129,9 @@
HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED
|| service.mContext.checkCallingOrSelfPermission(HIDE_OVERLAY_WINDOWS)
== PERMISSION_GRANTED;
+ mCanCreateSystemApplicationOverlay =
+ service.mContext.checkCallingOrSelfPermission(SYSTEM_APPLICATION_OVERLAY)
+ == PERMISSION_GRANTED;
mOverlaysCanBeHidden = !mCanAddInternalSystemWindow
&& !mService.mAtmInternal.isCallerRecents(mUid);
mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
@@ -673,8 +678,8 @@
boolean changed;
- if (mOverlaysCanBeHidden) {
- // We want to track non-system signature apps adding alert windows so we can post an
+ if (mOverlaysCanBeHidden && !mCanCreateSystemApplicationOverlay) {
+ // We want to track non-system apps adding alert windows so we can post an
// on-going notification for the user to control their visibility.
if (visible) {
changed = mAlertWindowSurfaces.add(surfaceController);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a2a6985..cc98230 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1407,7 +1407,6 @@
// from the display, so we should probably consolidate it there instead.
if (getParent() == null && mDisplayContent != null) {
- EventLogTags.writeWmStackRemoved(getRootTaskId());
mDisplayContent = null;
mWmService.mWindowPlacerLocked.requestTraversal();
}
@@ -2826,9 +2825,7 @@
getResolvedOverrideConfiguration().windowConfiguration.getBounds();
if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
- computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
- newParentConfig.windowConfiguration.getBounds(),
- newParentConfig.orientation);
+ computeFullscreenBounds(outOverrideBounds, newParentConfig);
// The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
// the parent or display is smaller than the size, the content may be cropped.
return;
@@ -2868,19 +2865,19 @@
* {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
* orientation change and the requested orientation is different from the parent.
*/
- void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
- @NonNull Rect parentBounds, int parentOrientation) {
+ void computeFullscreenBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) {
// In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
outBounds.setEmpty();
if (handlesOrientationChangeFromDescendant()) {
+ // No need to letterbox at task level. Display will handle fixed-orientation requests.
return;
}
- if (refActivity == null) {
- // Use the top activity as the reference of orientation. Don't include overlays because
- // it is usually not the actual content or just temporarily shown.
- // E.g. ForcedResizableInfoActivity.
- refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
- }
+
+ final int parentOrientation = newParentConfig.orientation;
+ // Use the top activity as the reference of orientation. Don't include overlays because
+ // it is usually not the actual content or just temporarily shown.
+ // E.g. ForcedResizableInfoActivity.
+ final ActivityRecord refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
// If the task or the reference activity requires a different orientation (either by
// override or activityInfo), make it fit the available bounds by scaling down its bounds.
@@ -2892,11 +2889,17 @@
return;
}
- if (refActivity != null && refActivity.hasCompatDisplayInsets()) {
+ final ActivityRecord.CompatDisplayInsets compatDisplayInsets =
+ refActivity == null ? null : refActivity.getCompatDisplayInsets();
+ if (compatDisplayInsets != null && !compatDisplayInsets.mIsTaskLetterboxed) {
// App prefers to keep its original size.
+ // If the size compat is from previous task letterboxing, we may want to have task
+ // letterbox again, otherwise it will show the size compat restart button even if the
+ // restart bounds will be the same.
return;
}
+ final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
final int parentWidth = parentBounds.width();
final int parentHeight = parentBounds.height();
float aspect = Math.max(parentWidth, parentHeight)
@@ -2931,6 +2934,18 @@
final int left = parentBounds.centerX() - width / 2;
outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
}
+
+ if (compatDisplayInsets != null) {
+ compatDisplayInsets.getBoundsByRotation(
+ mTmpBounds, newParentConfig.windowConfiguration.getRotation());
+ if (outBounds.width() != mTmpBounds.width()
+ || outBounds.height() != mTmpBounds.height()) {
+ // The app shouldn't be resized, we only do task letterboxing if the compat bounds
+ // is also from the same task letterbox. Otherwise, clear the task bounds to show
+ // app in size compat mode.
+ outBounds.setEmpty();
+ }
+ }
}
Rect updateOverrideConfigurationFromLaunchBounds() {
@@ -4094,6 +4109,7 @@
info.topActivityInfo = mReuseActivitiesReport.top != null
? mReuseActivitiesReport.top.info
: null;
+ info.launchCookies.clear();
info.addLaunchCookie(mLaunchCookie);
forAllActivities(r -> {
info.addLaunchCookie(r.mLaunchCookie);
@@ -4413,7 +4429,8 @@
if (mRootProcess != null) {
pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
}
- pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
+ pw.print(prefix); pw.print("taskId=" + mTaskId);
+ pw.println(" rootTaskId=" + getRootTaskId());
pw.print(prefix); pw.print("mHasBeenVisible="); pw.println(getHasBeenVisible());
pw.print(prefix); pw.print("mResizeMode=");
pw.print(ActivityInfo.resizeModeToString(mResizeMode));
@@ -6035,8 +6052,6 @@
// If the top activity is the resumed one, nothing to do.
if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
- // The activity may be waiting for stop, but that is no longer appropriate for it.
- mTaskSupervisor.mStoppingActivities.remove(next);
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
executeAppTransition(options);
@@ -7161,7 +7176,7 @@
if (needSep) {
pw.println();
}
- pw.println(" Stack #" + getRootTaskId()
+ pw.println(" RootTask #" + getRootTaskId()
+ ": type=" + activityTypeToString(getActivityType())
+ " mode=" + windowingModeToString(getWindowingMode()));
pw.println(" isSleeping=" + shouldSleepActivities());
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 2ebdda6..db26e05 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -19,7 +19,6 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -1259,7 +1258,7 @@
}
mLastFocusedRootTask = prevFocusedTask;
- EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser,
+ EventLogTags.writeWmFocusedRootTask(mRootWindowContainer.mCurrentUser,
mDisplayContent.mDisplayId,
currentFocusedTask == null ? -1 : currentFocusedTask.getRootTaskId(),
mLastFocusedRootTask == null ? -1 : mLastFocusedRootTask.getRootTaskId(),
@@ -1848,9 +1847,6 @@
// Keep the order from bottom to top.
int numRootTasks = mChildren.size();
- final boolean splitScreenActivated = toDisplayArea.isSplitScreenModeActivated();
- final Task splitScreenRoot = splitScreenActivated ? toDisplayArea
- .getTopRootTaskInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) : null;
for (int i = 0; i < numRootTasks; i++) {
final WindowContainer child = mChildren.get(i);
if (child.asTaskDisplayArea() != null) {
@@ -1866,10 +1862,12 @@
|| task.mCreatedByOrganizer) {
task.finishAllActivitiesImmediately();
} else {
- // Reparent the root task to the root task of secondary-split-screen or display
- // area.
- task.reparent(task.supportsSplitScreenWindowingMode() && splitScreenRoot != null
- ? splitScreenRoot : toDisplayArea, POSITION_TOP);
+ // Reparent task to corresponding launch root or display area.
+ final WindowContainer launchRoot = task.supportsSplitScreenWindowingMode()
+ ? toDisplayArea.getLaunchRootTask(
+ task.getWindowingMode(), task.getActivityType())
+ : null;
+ task.reparent(launchRoot == null ? toDisplayArea : launchRoot, POSITION_TOP);
// Set the windowing mode to undefined by default to let the root task inherited the
// windowing mode.
@@ -1881,14 +1879,19 @@
i -= numRootTasks - mChildren.size();
numRootTasks = mChildren.size();
}
- if (lastReparentedRootTask != null && splitScreenActivated) {
- if (!lastReparentedRootTask.supportsSplitScreenWindowingMode()) {
+
+ if (lastReparentedRootTask != null) {
+ if (toDisplayArea.isSplitScreenModeActivated()
+ && !lastReparentedRootTask.supportsSplitScreenWindowingMode()) {
+ // Dismiss split screen if the last reparented root task doesn't support split mode.
mAtmService.getTaskChangeNotificationController()
.notifyActivityDismissingDockedStack();
toDisplayArea.onSplitScreenModeDismissed(lastReparentedRootTask);
- } else if (splitScreenRoot != null) {
- // update focus
- splitScreenRoot.moveToFront("display-removed");
+ } else if (!lastReparentedRootTask.isRootTask()) {
+ // Update focus when the last reparented root task is not a root task anymore.
+ // (For example, if it has been reparented to a split screen root task, move the
+ // focus to the split root task)
+ lastReparentedRootTask.getRootTask().moveToFront("display-removed");
}
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 9a83ac7..65247d0 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -555,6 +555,7 @@
changed = (cfgChanges & REPORT_CONFIGS) != 0;
}
if (!(changed || force)) {
+ // mTmpTaskInfo will be reused next time.
return;
}
final RunningTaskInfo newInfo = mTmpTaskInfo;
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index b37e3c4..46aea23 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -50,6 +50,7 @@
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.animation.Animation;
+import android.window.IRemoteTransition;
import android.window.TransitionInfo;
import com.android.internal.annotations.VisibleForTesting;
@@ -101,6 +102,7 @@
private @WindowManager.TransitionFlags int mFlags;
private final TransitionController mController;
private final BLASTSyncEngine mSyncEngine;
+ private IRemoteTransition mRemoteTransition = null;
/**
* This is a leash to put animating surfaces into flatly without clipping/ordering issues. It
@@ -235,8 +237,14 @@
if (target.getParent() != null) {
// Ensure surfaceControls are re-parented back into the hierarchy.
t.reparent(target.getSurfaceControl(), target.getParent().getSurfaceControl());
+ t.setLayer(target.getSurfaceControl(), target.getLastLayer());
+ // TODO(shell-transitions): Once all remotables have been moved, see if there is
+ // a more appropriate place to do the following. This may
+ // involve passing an SF transaction from shell on finish.
target.getRelativePosition(tmpPos);
t.setPosition(target.getSurfaceControl(), tmpPos.x, tmpPos.y);
+ t.setCornerRadius(target.getSurfaceControl(), 0);
+ t.setShadowRadius(target.getSurfaceControl(), 0);
displays.add(target.getDisplayContent());
}
}
@@ -283,6 +291,14 @@
mSyncEngine.abort(mSyncId);
}
+ void setRemoteTransition(IRemoteTransition remoteTransition) {
+ mRemoteTransition = remoteTransition;
+ }
+
+ IRemoteTransition getRemoteTransition() {
+ return mRemoteTransition;
+ }
+
@Override
public void onTransactionReady(int syncId, SurfaceControl.Transaction transaction) {
if (syncId != mSyncId) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 0fe0afa..5f46ffe 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -26,7 +26,9 @@
import android.os.RemoteException;
import android.util.Slog;
import android.view.WindowManager;
+import android.window.IRemoteTransition;
import android.window.ITransitionPlayer;
+import android.window.TransitionRequestInfo;
import com.android.internal.protolog.ProtoLogGroup;
import com.android.internal.protolog.common.ProtoLog;
@@ -140,7 +142,7 @@
}
/**
- * @see #requestTransitionIfNeeded(int, int)
+ * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
*/
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@@ -148,9 +150,19 @@
return requestTransitionIfNeeded(type, 0 /* flags */, trigger);
}
+ /**
+ * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
+ */
+ @Nullable
+ Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
+ @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) {
+ return requestTransitionIfNeeded(type, flags, trigger, null /* remote */);
+ }
+
private static boolean isExistenceType(@WindowManager.TransitionType int type) {
return type == TRANSIT_OPEN || type == TRANSIT_CLOSE;
}
+
/**
* If a transition isn't requested yet, creates one and asks the TransitionPlayer (Shell) to
* start it. Collection can start immediately.
@@ -159,7 +171,8 @@
*/
@Nullable
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
- @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger) {
+ @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
+ @Nullable IRemoteTransition remoteTransition) {
if (mTransitionPlayer == null) {
return null;
}
@@ -169,7 +182,7 @@
mCollectingTransition.setReady(false);
} else {
newTransition = requestStartTransition(createTransition(type, flags),
- trigger != null ? trigger.asTask() : null);
+ trigger != null ? trigger.asTask() : null, remoteTransition);
}
if (trigger != null) {
if (isExistenceType(type)) {
@@ -183,7 +196,8 @@
/** Asks the transition player (shell) to start a created but not yet started transition. */
@NonNull
- Transition requestStartTransition(@NonNull Transition transition, @Nullable Task startTask) {
+ Transition requestStartTransition(@NonNull Transition transition, @Nullable Task startTask,
+ @Nullable IRemoteTransition remoteTransition) {
try {
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
"Requesting StartTransition: %s", transition);
@@ -192,7 +206,8 @@
info = new ActivityManager.RunningTaskInfo();
startTask.fillTaskInfo(info);
}
- mTransitionPlayer.requestStartTransition(transition.mType, transition, info);
+ mTransitionPlayer.requestStartTransition(transition, new TransitionRequestInfo(
+ transition.mType, info, remoteTransition));
} catch (RemoteException e) {
Slog.e(TAG, "Error requesting transition", e);
transition.start();
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index f627ca6..c4eb635 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -134,8 +134,6 @@
// Schedule next frame already such that back-pressure happens continuously.
scheduleAnimation();
- mTransaction.setFrameTimelineVsync(vsyncId);
-
mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
if (DEBUG_WINDOW_TRACE) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 663d91e..389f428 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -20,7 +20,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.os.Build.VERSION_CODES.Q;
import static android.os.IInputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
-import static android.view.Display.INVALID_DISPLAY;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.util.Preconditions.checkArgument;
@@ -201,8 +200,13 @@
private final Configuration mLastReportedConfiguration = new Configuration();
/** Whether the process configuration is waiting to be dispatched to the process. */
private boolean mHasPendingConfigurationChange;
- // Registered display id as a listener to override config change
- private int mDisplayId;
+
+ /**
+ * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
+ * registered.
+ */
+ @Nullable
+ private DisplayArea mDisplayArea;
private ActivityRecord mConfigActivityRecord;
// Whether the activity config override is allowed for this process.
private volatile boolean mIsActivityConfigOverrideAllowed = true;
@@ -252,7 +256,6 @@
mOwner = owner;
mListener = listener;
mAtm = atm;
- mDisplayId = INVALID_DISPLAY;
mBackgroundActivityStartCallback = mAtm.getBackgroundActivityStartCallback();
boolean isSysUiPackage = info.packageName.equals(
@@ -393,9 +396,9 @@
return mPendingUiClean;
}
- /** @return {@code true} if the process registered to a display as a config listener. */
- boolean registeredForDisplayConfigChanges() {
- return mDisplayId != INVALID_DISPLAY;
+ /** @return {@code true} if the process registered to a display area as a config listener. */
+ boolean registeredForDisplayAreaConfigChanges() {
+ return mDisplayArea != null;
}
/** @return {@code true} if the process registered to an activity as a config listener. */
@@ -443,11 +446,14 @@
return mRequiredAbi;
}
- /** Returns ID of display overriding the configuration for this process, or
- * INVALID_DISPLAY if no display is overriding. */
+ /**
+ * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
+ * registered.
+ */
@VisibleForTesting
- int getDisplayId() {
- return mDisplayId;
+ @Nullable
+ DisplayArea getDisplayArea() {
+ return mDisplayArea;
}
public void setDebugging(boolean debugging) {
@@ -1317,29 +1323,22 @@
return hasVisibleActivities;
}
- void registerDisplayConfigurationListener(DisplayContent displayContent) {
- if (displayContent == null) {
+ void registerDisplayAreaConfigurationListener(@Nullable DisplayArea displayArea) {
+ if (displayArea == null || displayArea.containsListener(this)) {
return;
}
- // A process can only register to one display to listen to the override configuration
- // change. Unregister existing listener if it has one before register the new one.
- unregisterDisplayConfigurationListener();
- unregisterActivityConfigurationListener();
- mDisplayId = displayContent.mDisplayId;
- displayContent.registerConfigurationChangeListener(this);
+ unregisterConfigurationListeners();
+ mDisplayArea = displayArea;
+ displayArea.registerConfigurationChangeListener(this);
}
@VisibleForTesting
- void unregisterDisplayConfigurationListener() {
- if (mDisplayId == INVALID_DISPLAY) {
+ void unregisterDisplayAreaConfigurationListener() {
+ if (mDisplayArea == null) {
return;
}
- final DisplayContent displayContent =
- mAtm.mRootWindowContainer.getDisplayContent(mDisplayId);
- if (displayContent != null) {
- displayContent.unregisterConfigurationChangeListener(this);
- }
- mDisplayId = INVALID_DISPLAY;
+ mDisplayArea.unregisterConfigurationChangeListener(this);
+ mDisplayArea = null;
onMergedOverrideConfigurationChanged(Configuration.EMPTY);
}
@@ -1349,10 +1348,7 @@
|| !mIsActivityConfigOverrideAllowed) {
return;
}
- // A process can only register to one activityRecord to listen to the override configuration
- // change. Unregister existing listener if it has one before register the new one.
- unregisterDisplayConfigurationListener();
- unregisterActivityConfigurationListener();
+ unregisterConfigurationListeners();
mConfigActivityRecord = activityRecord;
activityRecord.registerConfigurationChangeListener(this);
}
@@ -1367,6 +1363,16 @@
}
/**
+ * A process can only register to one {@link WindowContainer} to listen to the override
+ * configuration changes. Unregisters the existing listener if it has one before registers a
+ * new one.
+ */
+ private void unregisterConfigurationListeners() {
+ unregisterActivityConfigurationListener();
+ unregisterDisplayAreaConfigurationListener();
+ }
+
+ /**
* Check if activity configuration override for the activity process needs an update and perform
* if needed. By default we try to override the process configuration to match the top activity
* config to increase app compatibility with multi-window and multi-display. The process will
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 551e06d..124e120 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -67,10 +67,12 @@
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
@@ -131,6 +133,7 @@
import static com.android.server.wm.MoveAnimationSpecProto.FROM;
import static com.android.server.wm.MoveAnimationSpecProto.TO;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -722,7 +725,7 @@
static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */
- private final WindowProcessController mWpcForDisplayConfigChanges;
+ private final WindowProcessController mWpcForDisplayAreaConfigChanges;
/**
* Returns the visibility of the given {@link InternalInsetsType type} requested by the client.
@@ -914,7 +917,7 @@
mBaseLayer = 0;
mSubLayer = 0;
mWinAnimator = null;
- mWpcForDisplayConfigChanges = null;
+ mWpcForDisplayAreaConfigChanges = null;
return;
}
mDeathRecipient = deathRecipient;
@@ -968,8 +971,8 @@
parentWindow.addChild(this, sWindowSubLayerComparator);
}
- // System process or invalid process cannot register to display config change.
- mWpcForDisplayConfigChanges = (s.mPid == MY_PID || s.mPid < 0)
+ // System process or invalid process cannot register to display area config change.
+ mWpcForDisplayAreaConfigChanges = (s.mPid == MY_PID || s.mPid < 0)
? null
: service.mAtmService.getProcessController(s.mPid, s.mUid);
}
@@ -2281,7 +2284,8 @@
mWmService.mAccessibilityController.onWindowTransitionLocked(this, transit);
}
}
- final boolean isAnimating = isAnimating(TRANSITION | PARENTS)
+ final boolean isAnimating = mAnimatingExit || isAnimating(TRANSITION | PARENTS,
+ ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION)
&& (mActivityRecord == null || !mActivityRecord.isWaitingForTransitionStart());
final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null
&& mActivityRecord.isLastWindow(this);
@@ -2290,8 +2294,10 @@
// Also, If isn't the an animating starting window that is the last window in the app.
// We allow the removal of the non-animating starting window now as there is no
// additional window or animation that will trigger its removal.
- if (mWinAnimator.getShown() && mAnimatingExit
- && (!lastWindowIsStartingWindow || isAnimating)) {
+ if (mWinAnimator.getShown() && !lastWindowIsStartingWindow && isAnimating) {
+ // Make isSelfOrAncestorWindowAnimatingExit return true so onExitAnimationDone
+ // can proceed to remove this window.
+ mAnimatingExit = true;
// The exit animation is running or should run... wait for it!
ProtoLog.v(WM_DEBUG_ADD_REMOVE,
"Not removing %s due to exit animation", this);
@@ -3030,6 +3036,12 @@
|| (!isSystemAlertWindowType(mAttrs.type) && mAttrs.type != TYPE_TOAST)) {
return;
}
+
+ if (mAttrs.type == TYPE_APPLICATION_OVERLAY && mSession.mCanCreateSystemApplicationOverlay
+ && (mAttrs.privateFlags & SYSTEM_FLAG_SYSTEM_APPLICATION_OVERLAY) != 0) {
+ return;
+ }
+
if (mForceHideNonSystemOverlayWindow == forceHide) {
return;
}
@@ -3521,9 +3533,9 @@
return mActivityRecord.mFrozenMergedConfig.peek();
}
- // If the process has not registered to any display to listen to the configuration change,
- // we can simply return the mFullConfiguration as default.
- if (!registeredForDisplayConfigChanges()) {
+ // If the process has not registered to any display area to listen to the configuration
+ // change, we can simply return the mFullConfiguration as default.
+ if (!registeredForDisplayAreaConfigChanges()) {
return super.getConfiguration();
}
@@ -3534,13 +3546,13 @@
return mTempConfiguration;
}
- /** @return {@code true} if the process registered to a display as a config listener. */
- private boolean registeredForDisplayConfigChanges() {
+ /** @return {@code true} if the process registered to a display area as a config listener. */
+ private boolean registeredForDisplayAreaConfigChanges() {
final WindowState parentWindow = getParentWindow();
final WindowProcessController wpc = parentWindow != null
- ? parentWindow.mWpcForDisplayConfigChanges
- : mWpcForDisplayConfigChanges;
- return wpc != null && wpc.registeredForDisplayConfigChanges();
+ ? parentWindow.mWpcForDisplayAreaConfigChanges
+ : mWpcForDisplayAreaConfigChanges;
+ return wpc != null && wpc.registeredForDisplayAreaConfigChanges();
}
void fillClientWindowFrames(ClientWindowFrames outFrames) {
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index 43f50bf..729fa71 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -99,47 +99,17 @@
android_mallopt(M_INIT_ZYGOTE_CHILD_PROFILING, nullptr, 0);
}
-static int get_current_max_fd() {
- // Not actually guaranteed to be the max, but close enough for our purposes.
- int fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
- LOG_ALWAYS_FATAL_IF(fd == -1, "failed to open /dev/null: %s", strerror(errno));
- close(fd);
- return fd;
-}
+static void android_server_SystemServer_fdtrackAbort(JNIEnv*, jobject) {
+ raise(BIONIC_SIGNAL_FDTRACK);
-static const char kFdLeakEnableThresholdProperty[] = "persist.sys.debug.fdtrack_enable_threshold";
-static const char kFdLeakAbortThresholdProperty[] = "persist.sys.debug.fdtrack_abort_threshold";
-static const char kFdLeakCheckIntervalProperty[] = "persist.sys.debug.fdtrack_interval";
+ // Wait for a bit to allow fdtrack to dump backtraces to logcat.
+ std::this_thread::sleep_for(5s);
-static void android_server_SystemServer_spawnFdLeakCheckThread(JNIEnv*, jobject) {
+ // Abort on a different thread to avoid ART dumping runtime stacks.
std::thread([]() {
- pthread_setname_np(pthread_self(), "FdLeakCheckThread");
- bool loaded = false;
- while (true) {
- const int enable_threshold = GetIntProperty(kFdLeakEnableThresholdProperty, 1024);
- const int abort_threshold = GetIntProperty(kFdLeakAbortThresholdProperty, 2048);
- const int check_interval = GetIntProperty(kFdLeakCheckIntervalProperty, 120);
- int max_fd = get_current_max_fd();
- if (max_fd > enable_threshold && !loaded) {
- loaded = true;
- ALOGE("fd count above threshold of %d, starting fd backtraces", enable_threshold);
- if (dlopen("libfdtrack.so", RTLD_GLOBAL) == nullptr) {
- ALOGE("failed to load libfdtrack.so: %s", dlerror());
- }
- } else if (max_fd > abort_threshold) {
- raise(BIONIC_SIGNAL_FDTRACK);
-
- // Wait for a bit to allow fdtrack to dump backtraces to logcat.
- std::this_thread::sleep_for(5s);
-
- LOG_ALWAYS_FATAL(
- "b/140703823: aborting due to fd leak: check logs for fd "
- "backtraces");
- }
-
- std::this_thread::sleep_for(std::chrono::seconds(check_interval));
- }
- }).detach();
+ LOG_ALWAYS_FATAL("b/140703823: aborting due to fd leak: check logs for fd "
+ "backtraces");
+ }).join();
}
static jlong android_server_SystemServer_startIncrementalService(JNIEnv* env, jclass klass,
@@ -161,8 +131,7 @@
{"startHidlServices", "()V", (void*)android_server_SystemServer_startHidlServices},
{"initZygoteChildHeapProfiling", "()V",
(void*)android_server_SystemServer_initZygoteChildHeapProfiling},
- {"spawnFdLeakCheckThread", "()V",
- (void*)android_server_SystemServer_spawnFdLeakCheckThread},
+ {"fdtrackAbort", "()V", (void*)android_server_SystemServer_fdtrackAbort},
{"startIncrementalService", "()J",
(void*)android_server_SystemServer_startIncrementalService},
{"setIncrementalServiceSystemReady", "(J)V",
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index d0c2050..dc15b07 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -98,8 +98,10 @@
jmethodID notifySwitch;
jmethodID notifyInputChannelBroken;
jmethodID notifyNoFocusedWindowAnr;
- jmethodID notifyConnectionUnresponsive;
- jmethodID notifyConnectionResponsive;
+ jmethodID notifyWindowUnresponsive;
+ jmethodID notifyWindowResponsive;
+ jmethodID notifyMonitorUnresponsive;
+ jmethodID notifyMonitorResponsive;
jmethodID notifyFocusChanged;
jmethodID notifySensorEvent;
jmethodID notifySensorAccuracy;
@@ -159,7 +161,7 @@
jmethodID size;
} gSparseArrayClassInfo;
-struct InputSensorInfoOffsets {
+static struct InputSensorInfoOffsets {
jclass clazz;
// fields
jfieldID name;
@@ -288,9 +290,13 @@
void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
uint32_t policyFlags) override;
void notifyConfigurationChanged(nsecs_t when) override;
+ // ANR-related callbacks -- start
void notifyNoFocusedWindowAnr(const std::shared_ptr<InputApplicationHandle>& handle) override;
- void notifyConnectionUnresponsive(const sp<IBinder>& token, const std::string& reason) override;
- void notifyConnectionResponsive(const sp<IBinder>& token) override;
+ void notifyWindowUnresponsive(const sp<IBinder>& token, const std::string& reason) override;
+ void notifyWindowResponsive(const sp<IBinder>& token) override;
+ void notifyMonitorUnresponsive(int32_t pid, const std::string& reason) override;
+ void notifyMonitorResponsive(int32_t pid) override;
+ // ANR-related callbacks -- end
void notifyInputChannelBroken(const sp<IBinder>& token) override;
void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) override;
void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
@@ -775,10 +781,10 @@
checkAndClearExceptionFromCallback(env, "notifyNoFocusedWindowAnr");
}
-void NativeInputManager::notifyConnectionUnresponsive(const sp<IBinder>& token,
- const std::string& reason) {
+void NativeInputManager::notifyWindowUnresponsive(const sp<IBinder>& token,
+ const std::string& reason) {
#if DEBUG_INPUT_DISPATCHER_POLICY
- ALOGD("notifyConnectionUnresponsive");
+ ALOGD("notifyWindowUnresponsive");
#endif
ATRACE_CALL();
@@ -788,14 +794,14 @@
jobject tokenObj = javaObjectForIBinder(env, token);
ScopedLocalRef<jstring> reasonObj(env, env->NewStringUTF(reason.c_str()));
- env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyConnectionUnresponsive, tokenObj,
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyWindowUnresponsive, tokenObj,
reasonObj.get());
- checkAndClearExceptionFromCallback(env, "notifyConnectionUnresponsive");
+ checkAndClearExceptionFromCallback(env, "notifyWindowUnresponsive");
}
-void NativeInputManager::notifyConnectionResponsive(const sp<IBinder>& token) {
+void NativeInputManager::notifyWindowResponsive(const sp<IBinder>& token) {
#if DEBUG_INPUT_DISPATCHER_POLICY
- ALOGD("notifyConnectionResponsive");
+ ALOGD("notifyWindowResponsive");
#endif
ATRACE_CALL();
@@ -804,8 +810,37 @@
jobject tokenObj = javaObjectForIBinder(env, token);
- env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyConnectionResponsive, tokenObj);
- checkAndClearExceptionFromCallback(env, "notifyConnectionResponsive");
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyWindowResponsive, tokenObj);
+ checkAndClearExceptionFromCallback(env, "notifyWindowResponsive");
+}
+
+void NativeInputManager::notifyMonitorUnresponsive(int32_t pid, const std::string& reason) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+ ALOGD("notifyMonitorUnresponsive");
+#endif
+ ATRACE_CALL();
+
+ JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
+
+ ScopedLocalRef<jstring> reasonObj(env, env->NewStringUTF(reason.c_str()));
+
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyMonitorUnresponsive, pid,
+ reasonObj.get());
+ checkAndClearExceptionFromCallback(env, "notifyMonitorUnresponsive");
+}
+
+void NativeInputManager::notifyMonitorResponsive(int32_t pid) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+ ALOGD("notifyMonitorResponsive");
+#endif
+ ATRACE_CALL();
+
+ JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
+
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyMonitorResponsive, pid);
+ checkAndClearExceptionFromCallback(env, "notifyMonitorResponsive");
}
void NativeInputManager::notifyInputChannelBroken(const sp<IBinder>& token) {
@@ -2202,12 +2237,18 @@
GET_METHOD_ID(gServiceClassInfo.notifyNoFocusedWindowAnr, clazz, "notifyNoFocusedWindowAnr",
"(Landroid/view/InputApplicationHandle;)V");
- GET_METHOD_ID(gServiceClassInfo.notifyConnectionUnresponsive, clazz,
- "notifyConnectionUnresponsive", "(Landroid/os/IBinder;Ljava/lang/String;)V");
+ GET_METHOD_ID(gServiceClassInfo.notifyWindowUnresponsive, clazz, "notifyWindowUnresponsive",
+ "(Landroid/os/IBinder;Ljava/lang/String;)V");
- GET_METHOD_ID(gServiceClassInfo.notifyConnectionResponsive, clazz, "notifyConnectionResponsive",
+ GET_METHOD_ID(gServiceClassInfo.notifyMonitorUnresponsive, clazz, "notifyMonitorUnresponsive",
+ "(ILjava/lang/String;)V");
+
+ GET_METHOD_ID(gServiceClassInfo.notifyWindowResponsive, clazz, "notifyWindowResponsive",
"(Landroid/os/IBinder;)V");
+ GET_METHOD_ID(gServiceClassInfo.notifyMonitorResponsive, clazz, "notifyMonitorResponsive",
+ "(I)V");
+
GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
"filterInputEvent", "(Landroid/view/InputEvent;I)Z");
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 35aad3e..b2d6b15 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -2709,7 +2709,7 @@
}
static jboolean android_location_gnss_hal_GnssNative_start_measurement_collection(
- JNIEnv* /* env */, jclass, jboolean enableFullTracking) {
+ JNIEnv* /* env */, jclass, jboolean enableFullTracking, jboolean enableCorrVecOutputs) {
if (gnssMeasurementIface == nullptr) {
ALOGE("%s: IGnssMeasurement interface not available.", __func__);
return JNI_FALSE;
@@ -2717,7 +2717,7 @@
return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>(
mCallbacksObj),
- enableFullTracking);
+ enableFullTracking, enableCorrVecOutputs);
}
static jboolean android_location_gnss_hal_GnssNative_stop_measurement_collection(JNIEnv* env,
@@ -3211,7 +3211,7 @@
/* name, signature, funcPtr */
{"native_is_measurement_supported", "()Z",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_is_measurement_supported)},
- {"native_start_measurement_collection", "(Z)Z",
+ {"native_start_measurement_collection", "(ZZ)Z",
reinterpret_cast<void*>(
android_location_gnss_hal_GnssNative_start_measurement_collection)},
{"native_stop_measurement_collection", "()Z",
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 631e185..7b379e5 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -68,6 +68,9 @@
static constexpr auto PollTimeoutMs = 5000;
static constexpr auto TraceTagCheckInterval = 1s;
+static constexpr auto WaitOnEofMinInterval = 10ms;
+static constexpr auto WaitOnEofMaxInterval = 1s;
+
struct JniIds {
jclass packageManagerShellCommandDataLoader;
jmethodID pmscdLookupShellCommand;
@@ -485,14 +488,16 @@
if (read == 0) {
if (waitOnEof) {
// eof of stdin, waiting...
- ALOGE("eof of stdin, waiting...: %d, remaining: %d, block: %d, read: %d",
- int(totalSize), int(remaining), int(blockIdx), int(read));
- using namespace std::chrono_literals;
- std::this_thread::sleep_for(10ms);
- continue;
+ if (doWaitOnEof()) {
+ continue;
+ } else {
+ return false;
+ }
}
break;
}
+ resetWaitOnEof();
+
if (read < 0) {
return false;
}
@@ -776,6 +781,21 @@
return fileId;
}
+ // Waiting with exponential backoff, maximum total time ~1.2sec.
+ bool doWaitOnEof() {
+ if (mWaitOnEofInterval >= WaitOnEofMaxInterval) {
+ resetWaitOnEof();
+ return false;
+ }
+ auto result = mWaitOnEofInterval;
+ mWaitOnEofInterval =
+ std::min<std::chrono::milliseconds>(mWaitOnEofInterval * 2, WaitOnEofMaxInterval);
+ std::this_thread::sleep_for(result);
+ return true;
+ }
+
+ void resetWaitOnEof() { mWaitOnEofInterval = WaitOnEofMinInterval; }
+
JavaVM* const mJvm;
std::string mArgs;
android::dataloader::FilesystemConnectorPtr mIfs = nullptr;
@@ -786,6 +806,7 @@
std::thread mReceiverThread;
std::atomic<bool> mStopReceiving = false;
std::atomic<bool> mReadLogsEnabled = false;
+ std::chrono::milliseconds mWaitOnEofInterval{WaitOnEofMinInterval};
/** Tracks which files have been requested */
std::unordered_set<FileIdx> mRequestedFiles;
};
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 4e1a234..a5311f3 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -261,7 +261,7 @@
void onDeviceAvailable(const TvInputDeviceInfo& info);
void onDeviceUnavailable(int deviceId);
- void onStreamConfigurationsChanged(int deviceId);
+ void onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus);
void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded);
private:
@@ -519,7 +519,7 @@
deviceId);
}
-void JTvInputHal::onStreamConfigurationsChanged(int deviceId) {
+void JTvInputHal::onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus) {
{
Mutex::Autolock autoLock(&mLock);
KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
@@ -529,10 +529,8 @@
connections.clear();
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(
- mThiz,
- gTvInputHalClassInfo.streamConfigsChanged,
- deviceId);
+ env->CallVoidMethod(mThiz, gTvInputHalClassInfo.streamConfigsChanged, deviceId,
+ cableConnectionStatus);
}
void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) {
@@ -572,7 +570,8 @@
mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId);
} break;
case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED: {
- mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId);
+ int cableConnectionStatus = static_cast<int>(mEvent.deviceInfo.cableConnectionStatus);
+ mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId, cableConnectionStatus);
} break;
default:
ALOGE("Unrecognizable event");
@@ -688,9 +687,8 @@
"deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V");
GET_METHOD_ID(
gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V");
- GET_METHOD_ID(
- gTvInputHalClassInfo.streamConfigsChanged, clazz,
- "streamConfigsChangedFromNative", "(I)V");
+ GET_METHOD_ID(gTvInputHalClassInfo.streamConfigsChanged, clazz,
+ "streamConfigsChangedFromNative", "(II)V");
GET_METHOD_ID(
gTvInputHalClassInfo.firstFrameCaptured, clazz,
"firstFrameCapturedFromNative", "(II)V");
diff --git a/services/core/jni/gnss/GnssMeasurement.cpp b/services/core/jni/gnss/GnssMeasurement.cpp
index 2261c38..663d839 100644
--- a/services/core/jni/gnss/GnssMeasurement.cpp
+++ b/services/core/jni/gnss/GnssMeasurement.cpp
@@ -50,8 +50,9 @@
: mIGnssMeasurement(iGnssMeasurement) {}
jboolean GnssMeasurement::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
- auto status = mIGnssMeasurement->setCallback(callback->getAidl(), enableFullTracking);
+ bool enableFullTracking, bool enableCorrVecOutputs) {
+ auto status = mIGnssMeasurement->setCallback(callback->getAidl(), enableFullTracking,
+ enableCorrVecOutputs);
return checkAidlStatus(status, "IGnssMeasurement setCallback() failed.");
}
@@ -66,9 +67,12 @@
: mIGnssMeasurement_V1_0(iGnssMeasurement) {}
jboolean GnssMeasurement_V1_0::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
+ bool enableFullTracking, bool enableCorrVecOutputs) {
if (enableFullTracking == true) {
- ALOGW("Full tracking is mode not supported in 1.0 GNSS HAL.");
+ ALOGW("Full tracking mode is not supported in 1.0 GNSS HAL.");
+ }
+ if (enableCorrVecOutputs == true) {
+ ALOGW("Correlation vector output is not supported in 1.0 GNSS HAL.");
}
auto status = mIGnssMeasurement_V1_0->setCallback(callback->getHidl());
if (!checkHidlReturn(status, "IGnssMeasurement setCallback() failed.")) {
@@ -89,7 +93,10 @@
: GnssMeasurement_V1_0{iGnssMeasurement}, mIGnssMeasurement_V1_1(iGnssMeasurement) {}
jboolean GnssMeasurement_V1_1::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
+ bool enableFullTracking, bool enableCorrVecOutputs) {
+ if (enableCorrVecOutputs == true) {
+ ALOGW("Correlation vector output is not supported in 1.1 GNSS HAL.");
+ }
auto status = mIGnssMeasurement_V1_1->setCallback_1_1(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_V1_1() failed.")) {
return JNI_FALSE;
@@ -104,7 +111,10 @@
: GnssMeasurement_V1_1{iGnssMeasurement}, mIGnssMeasurement_V2_0(iGnssMeasurement) {}
jboolean GnssMeasurement_V2_0::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
+ bool enableFullTracking, bool enableCorrVecOutputs) {
+ if (enableCorrVecOutputs == true) {
+ ALOGW("Correlation vector output is not supported in 2.0 GNSS HAL.");
+ }
auto status = mIGnssMeasurement_V2_0->setCallback_2_0(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_0() failed.")) {
return JNI_FALSE;
@@ -119,7 +129,10 @@
: GnssMeasurement_V2_0{iGnssMeasurement}, mIGnssMeasurement_V2_1(iGnssMeasurement) {}
jboolean GnssMeasurement_V2_1::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) {
+ bool enableFullTracking, bool enableCorrVecOutputs) {
+ if (enableCorrVecOutputs == true) {
+ ALOGW("Correlation vector output is not supported in 2.1 GNSS HAL.");
+ }
auto status = mIGnssMeasurement_V2_1->setCallback_2_1(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_1() failed.")) {
return JNI_FALSE;
diff --git a/services/core/jni/gnss/GnssMeasurement.h b/services/core/jni/gnss/GnssMeasurement.h
index e64336f..f0752cd 100644
--- a/services/core/jni/gnss/GnssMeasurement.h
+++ b/services/core/jni/gnss/GnssMeasurement.h
@@ -38,7 +38,7 @@
public:
virtual ~GnssMeasurementInterface() {}
virtual jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) = 0;
+ bool enableFullTracking, bool enableCorrVecOutputs) = 0;
virtual jboolean close() = 0;
};
@@ -46,7 +46,7 @@
public:
GnssMeasurement(const sp<android::hardware::gnss::IGnssMeasurementInterface>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
jboolean close() override;
private:
@@ -58,7 +58,7 @@
GnssMeasurement_V1_0(
const sp<android::hardware::gnss::V1_0::IGnssMeasurement>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
jboolean close() override;
private:
@@ -70,7 +70,7 @@
GnssMeasurement_V1_1(
const sp<android::hardware::gnss::V1_1::IGnssMeasurement>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
private:
const sp<android::hardware::gnss::V1_1::IGnssMeasurement> mIGnssMeasurement_V1_1;
@@ -81,7 +81,7 @@
GnssMeasurement_V2_0(
const sp<android::hardware::gnss::V2_0::IGnssMeasurement>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
private:
const sp<android::hardware::gnss::V2_0::IGnssMeasurement> mIGnssMeasurement_V2_0;
@@ -92,7 +92,7 @@
GnssMeasurement_V2_1(
const sp<android::hardware::gnss::V2_1::IGnssMeasurement>& iGnssMeasurement);
jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
- bool enableFullTracking) override;
+ bool enableFullTracking, bool enableCorrVecOutputs) override;
private:
const sp<android::hardware::gnss::V2_1::IGnssMeasurement> mIGnssMeasurement_V2_1;
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
index bb020f3..757381d 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.cpp
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -21,19 +21,47 @@
namespace android::gnss {
using binder::Status;
+using hardware::gnss::CorrelationVector;
using hardware::gnss::ElapsedRealtime;
using hardware::gnss::GnssClock;
using hardware::gnss::GnssData;
using hardware::gnss::GnssMeasurement;
+using hardware::gnss::SatellitePvt;
+jclass class_arrayList;
+jclass class_clockInfo;
+jclass class_correlationVectorBuilder;
jclass class_gnssMeasurementsEvent;
jclass class_gnssMeasurement;
jclass class_gnssClock;
+jclass class_positionEcef;
+jclass class_satellitePvtBuilder;
+jclass class_velocityEcef;
+jmethodID method_arrayListAdd;
+jmethodID method_arrayListCtor;
+jmethodID method_correlationVectorBuilderBuild;
+jmethodID method_correlationVectorBuilderCtor;
+jmethodID method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond;
+jmethodID method_correlationVectorBuilderSetMagnitude;
+jmethodID method_correlationVectorBuilderSetSamplingStartMeters;
+jmethodID method_correlationVectorBuilderSetSamplingWidthMeters;
jmethodID method_gnssMeasurementsEventCtor;
+jmethodID method_gnssMeasurementsSetCorrelationVectors;
+jmethodID method_gnssMeasurementsSetSatellitePvt;
jmethodID method_gnssClockCtor;
jmethodID method_gnssMeasurementCtor;
jmethodID method_reportMeasurementData;
+jmethodID method_satellitePvtBuilderBuild;
+jmethodID method_satellitePvtBuilderCtor;
+jmethodID method_satellitePvtBuilderSetPositionEcef;
+jmethodID method_satellitePvtBuilderSetVelocityEcef;
+jmethodID method_satellitePvtBuilderSetClockInfo;
+jmethodID method_satellitePvtBuilderSetIonoDelayMeters;
+jmethodID method_satellitePvtBuilderSetTropoDelayMeters;
+jmethodID method_positionEcef;
+jmethodID method_velocityEcef;
+jmethodID method_clockInfo;
void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz) {
method_reportMeasurementData = env->GetMethodID(clazz, "reportMeasurementData",
@@ -47,10 +75,77 @@
jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
class_gnssMeasurement = (jclass)env->NewGlobalRef(gnssMeasurementClass);
method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
+ method_gnssMeasurementsSetSatellitePvt =
+ env->GetMethodID(class_gnssMeasurement, "setSatellitePvt",
+ "(Landroid/location/SatellitePvt;)V");
+ method_gnssMeasurementsSetCorrelationVectors =
+ env->GetMethodID(class_gnssMeasurement, "setCorrelationVectors",
+ "(Ljava/util/Collection;)V");
jclass gnssClockClass = env->FindClass("android/location/GnssClock");
class_gnssClock = (jclass)env->NewGlobalRef(gnssClockClass);
method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
+
+ jclass satellitePvtBuilder = env->FindClass("android/location/SatellitePvt$Builder");
+ class_satellitePvtBuilder = (jclass)env->NewGlobalRef(satellitePvtBuilder);
+ method_satellitePvtBuilderCtor = env->GetMethodID(class_satellitePvtBuilder, "<init>", "()V");
+ method_satellitePvtBuilderSetPositionEcef =
+ env->GetMethodID(class_satellitePvtBuilder, "setPositionEcef",
+ "(Landroid/location/SatellitePvt$PositionEcef;)"
+ "Landroid/location/SatellitePvt$Builder;");
+ method_satellitePvtBuilderSetVelocityEcef =
+ env->GetMethodID(class_satellitePvtBuilder, "setVelocityEcef",
+ "(Landroid/location/SatellitePvt$VelocityEcef;)"
+ "Landroid/location/SatellitePvt$Builder;");
+ method_satellitePvtBuilderSetClockInfo =
+ env->GetMethodID(class_satellitePvtBuilder, "setClockInfo",
+ "(Landroid/location/SatellitePvt$ClockInfo;)"
+ "Landroid/location/SatellitePvt$Builder;");
+ method_satellitePvtBuilderSetIonoDelayMeters =
+ env->GetMethodID(class_satellitePvtBuilder, "setIonoDelayMeters",
+ "(D)Landroid/location/SatellitePvt$Builder;");
+ method_satellitePvtBuilderSetTropoDelayMeters =
+ env->GetMethodID(class_satellitePvtBuilder, "setTropoDelayMeters",
+ "(D)Landroid/location/SatellitePvt$Builder;");
+ method_satellitePvtBuilderBuild = env->GetMethodID(class_satellitePvtBuilder, "build",
+ "()Landroid/location/SatellitePvt;");
+
+ jclass positionEcefClass = env->FindClass("android/location/SatellitePvt$PositionEcef");
+ class_positionEcef = (jclass)env->NewGlobalRef(positionEcefClass);
+ method_positionEcef = env->GetMethodID(class_positionEcef, "<init>", "(DDDD)V");
+
+ jclass velocityEcefClass = env->FindClass("android/location/SatellitePvt$VelocityEcef");
+ class_velocityEcef = (jclass)env->NewGlobalRef(velocityEcefClass);
+ method_velocityEcef = env->GetMethodID(class_velocityEcef, "<init>", "(DDDD)V");
+
+ jclass clockInfoClass = env->FindClass("android/location/SatellitePvt$ClockInfo");
+ class_clockInfo = (jclass)env->NewGlobalRef(clockInfoClass);
+ method_clockInfo = env->GetMethodID(class_clockInfo, "<init>", "(DDD)V");
+
+ jclass correlationVectorBuilder = env->FindClass("android/location/CorrelationVector$Builder");
+ class_correlationVectorBuilder = (jclass)env->NewGlobalRef(correlationVectorBuilder);
+ method_correlationVectorBuilderCtor =
+ env->GetMethodID(class_correlationVectorBuilder, "<init>", "()V");
+ method_correlationVectorBuilderSetMagnitude =
+ env->GetMethodID(class_correlationVectorBuilder, "setMagnitude",
+ "([I)Landroid/location/CorrelationVector$Builder;");
+ method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond =
+ env->GetMethodID(class_correlationVectorBuilder, "setFrequencyOffsetMetersPerSecond",
+ "(I)Landroid/location/CorrelationVector$Builder;");
+ method_correlationVectorBuilderSetSamplingStartMeters =
+ env->GetMethodID(class_correlationVectorBuilder, "setSamplingStartMeters",
+ "(D)Landroid/location/CorrelationVector$Builder;");
+ method_correlationVectorBuilderSetSamplingWidthMeters =
+ env->GetMethodID(class_correlationVectorBuilder, "setSamplingWidthMeters",
+ "(D)Landroid/location/CorrelationVector$Builder;");
+ method_correlationVectorBuilderBuild =
+ env->GetMethodID(class_correlationVectorBuilder, "build",
+ "()Landroid/location/CorrelationVector;");
+
+ jclass arrayListClass = env->FindClass("java/util/ArrayList");
+ class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
+ method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
+ method_arrayListAdd = env->GetMethodID(class_arrayList, "add", "(Ljava/lang/Object;)Z");
}
void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock,
@@ -212,6 +307,90 @@
SET(CarrierFrequencyHz, static_cast<float>(measurement.signalType.carrierFrequencyHz));
}
+ if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_SATELLITE_PVT)) {
+ const SatellitePvt& satellitePvt = measurement.satellitePvt;
+ jobject positionEcef = env->NewObject(class_positionEcef, method_positionEcef,
+ satellitePvt.satPosEcef.posXMeters,
+ satellitePvt.satPosEcef.posYMeters,
+ satellitePvt.satPosEcef.posZMeters,
+ satellitePvt.satPosEcef.ureMeters);
+ jobject velocityEcef =
+ env->NewObject(class_velocityEcef, method_velocityEcef,
+ satellitePvt.satVelEcef.velXMps, satellitePvt.satVelEcef.velYMps,
+ satellitePvt.satVelEcef.velZMps, satellitePvt.satVelEcef.ureRateMps);
+ jobject clockInfo = env->NewObject(class_clockInfo, method_clockInfo,
+ satellitePvt.satClockInfo.satHardwareCodeBiasMeters,
+ satellitePvt.satClockInfo.satTimeCorrectionMeters,
+ satellitePvt.satClockInfo.satClkDriftMps);
+ jobject satellitePvtBuilderObject =
+ env->NewObject(class_satellitePvtBuilder, method_satellitePvtBuilderCtor);
+
+ env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderSetPositionEcef,
+ positionEcef);
+ env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderSetVelocityEcef,
+ velocityEcef);
+ env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderSetClockInfo,
+ clockInfo);
+ env->CallObjectMethod(satellitePvtBuilderObject,
+ method_satellitePvtBuilderSetIonoDelayMeters,
+ satellitePvt.ionoDelayMeters);
+ env->CallObjectMethod(satellitePvtBuilderObject,
+ method_satellitePvtBuilderSetTropoDelayMeters,
+ satellitePvt.tropoDelayMeters);
+ jobject satellitePvtObject =
+ env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderBuild);
+
+ env->CallVoidMethod(object.get(), method_gnssMeasurementsSetSatellitePvt,
+ satellitePvtObject);
+
+ env->DeleteLocalRef(positionEcef);
+ env->DeleteLocalRef(velocityEcef);
+ env->DeleteLocalRef(clockInfo);
+ env->DeleteLocalRef(satellitePvtBuilderObject);
+ env->DeleteLocalRef(satellitePvtObject);
+ }
+
+ if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_CORRELATION_VECTOR)) {
+ jobject correlationVectorList = env->NewObject(class_arrayList, method_arrayListCtor);
+ for (uint16_t i = 0; i < measurement.correlationVectors.size(); ++i) {
+ const CorrelationVector& correlationVector = measurement.correlationVectors[i];
+ const std::vector<int32_t>& magnitudeVector = correlationVector.magnitude;
+
+ jsize numMagnitude = magnitudeVector.size();
+ jintArray magnitudeArray = env->NewIntArray(numMagnitude);
+ env->SetIntArrayRegion(magnitudeArray, 0, numMagnitude,
+ reinterpret_cast<const jint*>(magnitudeVector.data()));
+
+ jobject correlationVectorBuilderObject =
+ env->NewObject(class_correlationVectorBuilder,
+ method_correlationVectorBuilderCtor);
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetMagnitude, magnitudeArray);
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond,
+ correlationVector.frequencyOffsetMps);
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetSamplingStartMeters,
+ correlationVector.samplingStartM);
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderSetSamplingWidthMeters,
+ correlationVector.samplingWidthM);
+ jobject correlationVectorObject =
+ env->CallObjectMethod(correlationVectorBuilderObject,
+ method_correlationVectorBuilderBuild);
+
+ env->CallBooleanMethod(correlationVectorList, method_arrayListAdd,
+ correlationVectorObject);
+
+ env->DeleteLocalRef(magnitudeArray);
+ env->DeleteLocalRef(correlationVectorBuilderObject);
+ env->DeleteLocalRef(correlationVectorObject);
+ }
+ env->CallVoidMethod(object.get(), method_gnssMeasurementsSetCorrelationVectors,
+ correlationVectorList);
+ env->DeleteLocalRef(correlationVectorList);
+ }
+
jstring codeType = env->NewStringUTF(measurement.signalType.codeType.c_str());
SET(CodeType, codeType);
env->DeleteLocalRef(codeType);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 8b7f83f..55ba6c9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -109,7 +109,7 @@
return false;
}
- public String getEnrollmentSpecificId() {
+ public String getEnrollmentSpecificId(String callerPackage) {
return "";
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index 934f948..ba3ae45 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -459,7 +459,6 @@
}
policy.mFactoryResetReason = parser.getAttributeValue(null, ATTR_FACTORY_RESET_REASON);
- parser.next();
int outerDepth = parser.getDepth();
policy.mLockTaskPackages.clear();
policy.mAdminList.clear();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 83c5870..2975800 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -375,6 +375,9 @@
private static final String CALLED_FROM_PARENT = "calledFromParent";
private static final String NOT_CALLED_FROM_PARENT = "notCalledFromParent";
+ private static final String CREDENTIAL_MANAGEMENT_APP = "credentialManagementApp";
+ private static final String NOT_CREDENTIAL_MANAGEMENT_APP = "notCredentialManagementApp";
+
// Comprehensive list of delegations.
private static final String DELEGATIONS[] = {
DELEGATION_CERT_INSTALL,
@@ -3380,6 +3383,7 @@
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REMOVE_ACTIVE_ADMIN);
enforceUserUnlocked(userHandle);
synchronized (getLockObject()) {
@@ -3413,9 +3417,10 @@
getTargetSdk(profileOwner.getPackageName(), userHandle) > Build.VERSION_CODES.M;
}
- private boolean canSetPasswordQualityOnParent(String packageName, int userId) {
+ private boolean canSetPasswordQualityOnParent(String packageName, final CallerIdentity caller) {
return !mInjector.isChangeEnabled(
- PREVENT_SETTING_PASSWORD_QUALITY_ON_PARENT, packageName, userId);
+ PREVENT_SETTING_PASSWORD_QUALITY_ON_PARENT, packageName, caller.getUserId())
+ || isProfileOwnerOfOrganizationOwnedDevice(caller);
}
private boolean isPasswordLimitingAdminTargetingP(CallerIdentity caller) {
@@ -3444,7 +3449,7 @@
|| isPasswordLimitingAdminTargetingP(caller));
final boolean qualityMayApplyToParent =
- canSetPasswordQualityOnParent(who.getPackageName(), caller.getUserId());
+ canSetPasswordQualityOnParent(who.getPackageName(), caller);
if (!qualityMayApplyToParent) {
Preconditions.checkCallAuthorization(!parent,
"Profile Owner may not apply password quality requirements device-wide");
@@ -5139,6 +5144,7 @@
}
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
Preconditions.checkCallAuthorization(canManageCaCerts(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_INSTALL_CA_CERT);
final String alias = mInjector.binderWithCleanCallingIdentity(() -> {
String installedAlias = mCertificateMonitor.installCaCert(
@@ -5170,6 +5176,7 @@
}
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
Preconditions.checkCallAuthorization(canManageCaCerts(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_UNINSTALL_CA_CERT);
mInjector.binderWithCleanCallingIdentity(() -> {
mCertificateMonitor.uninstallCaCerts(caller.getUserHandle(), aliases);
@@ -5193,10 +5200,13 @@
byte[] cert, byte[] chain, String alias, boolean requestAccess,
boolean isUserSelectable) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
+ final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+ final boolean isCredentialManagementApp =
+ isCredentialManagementApp(caller, alias, isUserSelectable);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
- || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL)
- || isCredentialManagementApp(caller, alias, isUserSelectable))));
+ || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_INSTALL_KEY_PAIR);
final long id = mInjector.binderClearCallingIdentity();
try {
@@ -5205,6 +5215,7 @@
try {
IKeyChainService keyChain = keyChainConnection.getService();
if (!keyChain.installKeyPair(privKey, cert, chain, alias, KeyStore.UID_SELF)) {
+ logInstallKeyPairFailure(caller, isCredentialManagementApp);
return false;
}
if (requestAccess) {
@@ -5214,7 +5225,9 @@
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.INSTALL_KEY_PAIR)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate)
+ .setStrings(isCredentialManagementApp
+ ? CREDENTIAL_MANAGEMENT_APP : NOT_CREDENTIAL_MANAGEMENT_APP)
.write();
return true;
} catch (RemoteException e) {
@@ -5228,16 +5241,30 @@
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
+ logInstallKeyPairFailure(caller, isCredentialManagementApp);
return false;
}
+ private void logInstallKeyPairFailure(CallerIdentity caller,
+ boolean isCredentialManagementApp) {
+ if (!isCredentialManagementApp) {
+ return;
+ }
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums.CREDENTIAL_MANAGEMENT_APP_INSTALL_KEY_PAIR_FAILED)
+ .setStrings(caller.getPackageName())
+ .write();
+ }
+
@Override
public boolean removeKeyPair(ComponentName who, String callerPackage, String alias) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
+ final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+ final boolean isCredentialManagementApp = isCredentialManagementApp(caller, alias);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
- || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL)
- || isCredentialManagementApp(caller, alias))));
+ || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REMOVE_KEY_PAIR);
final long id = Binder.clearCallingIdentity();
try {
@@ -5248,7 +5275,9 @@
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.REMOVE_KEY_PAIR)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate)
+ .setStrings(isCredentialManagementApp
+ ? CREDENTIAL_MANAGEMENT_APP : NOT_CREDENTIAL_MANAGEMENT_APP)
.write();
return keyChain.removeKeyPair(alias);
} catch (RemoteException e) {
@@ -5472,6 +5501,8 @@
"Requested Device ID attestation but challenge is empty");
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
+ final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+ final boolean isCredentialManagementApp = isCredentialManagementApp(caller, alias);
if (deviceIdAttestationRequired && attestationUtilsFlags.length > 0) {
// TODO: replace enforce methods
enforceCallerCanRequestDeviceIdAttestation(caller);
@@ -5479,14 +5510,14 @@
} else {
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
- || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL)
- || isCredentialManagementApp(caller, alias))));
+ || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
}
// As the caller will be granted access to the key, ensure no UID was specified, as
// it will not have the desired effect.
if (keySpec.getUid() != KeyStore.UID_SELF) {
Log.e(LOG_TAG, "Only the caller can be granted access to the generated keypair.");
+ logGenerateKeyPairFailure(caller, isCredentialManagementApp);
return false;
}
@@ -5512,6 +5543,7 @@
DevicePolicyManager.KEY_GEN_STRONGBOX_UNAVAILABLE,
String.format("KeyChain error: %d", generationResult));
default:
+ logGenerateKeyPairFailure(caller, isCredentialManagementApp);
return false;
}
}
@@ -5536,15 +5568,17 @@
throw new UnsupportedOperationException(
"Device does not support Device ID attestation.");
}
+ logGenerateKeyPairFailure(caller, isCredentialManagementApp);
return false;
}
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.GENERATE_KEY_PAIR)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate)
.setInt(idAttestationFlags)
- .setStrings(algorithm)
+ .setStrings(algorithm, isCredentialManagementApp
+ ? CREDENTIAL_MANAGEMENT_APP : NOT_CREDENTIAL_MANAGEMENT_APP)
.write();
return true;
}
@@ -5556,9 +5590,21 @@
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
+ logGenerateKeyPairFailure(caller, isCredentialManagementApp);
return false;
}
+ private void logGenerateKeyPairFailure(CallerIdentity caller,
+ boolean isCredentialManagementApp) {
+ if (!isCredentialManagementApp) {
+ return;
+ }
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums.CREDENTIAL_MANAGEMENT_APP_GENERATE_KEY_PAIR_FAILED)
+ .setStrings(caller.getPackageName())
+ .write();
+ }
+
private void enforceIndividualAttestationSupportedIfRequested(int[] attestationUtilsFlags) {
for (int attestationFlag : attestationUtilsFlags) {
if (attestationFlag == USE_INDIVIDUAL_ATTESTATION
@@ -5574,10 +5620,11 @@
public boolean setKeyPairCertificate(ComponentName who, String callerPackage, String alias,
byte[] cert, byte[] chain, boolean isUserSelectable) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
+ final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
+ final boolean isCredentialManagementApp = isCredentialManagementApp(caller, alias);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
- || (caller.hasPackage() && (isCallerDelegate(caller, DELEGATION_CERT_INSTALL)
- || isCredentialManagementApp(caller, alias))));
+ || (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
final long id = mInjector.binderClearCallingIdentity();
try (final KeyChainConnection keyChainConnection =
@@ -5590,7 +5637,9 @@
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_KEY_PAIR_CERTIFICATE)
.setAdmin(caller.getPackageName())
- .setBoolean(/* isDelegate */ who == null)
+ .setBoolean(/* isDelegate */ isCallerDelegate)
+ .setStrings(isCredentialManagementApp
+ ? CREDENTIAL_MANAGEMENT_APP : NOT_CREDENTIAL_MANAGEMENT_APP)
.write();
return true;
} catch (InterruptedException e) {
@@ -6113,6 +6162,7 @@
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_ALWAYS_ON_VPN_PACKAGE);
final int userId = caller.getUserId();
mInjector.binderWithCleanCallingIdentity(() -> {
@@ -6456,6 +6506,8 @@
CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager
+ .OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY);
final int frpManagementAgentUid = getFrpManagementAgentUidOrThrow();
synchronized (getLockObject()) {
@@ -7353,6 +7405,7 @@
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
checkAllUsersAreAffiliatedWithDevice();
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REQUEST_BUGREPORT);
if (mBugreportCollectionManager.requestBugreport()) {
DevicePolicyEventLogger
@@ -7462,6 +7515,7 @@
if (parent) {
Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller));
}
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_CAMERA_DISABLED);
final int userHandle = caller.getUserId();
synchronized (getLockObject()) {
@@ -9212,6 +9266,7 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_RESTRICTIONS_PROVIDER);
synchronized (getLockObject()) {
int userHandle = caller.getUserId();
@@ -9810,8 +9865,14 @@
final long id = mInjector.binderClearCallingIdentity();
try {
- manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
- /* showDisclaimer= */ true);
+ if (!mInjector.userManagerIsHeadlessSystemUserMode()) {
+ manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
+ /* showDisclaimer= */ true);
+ } else if (VERBOSE_LOG) {
+ Slog.v(LOG_TAG, "createAndManageUser(): skipping manageUserUnchecked() on user "
+ + userHandle + " on headless system user as it will be called by "
+ + "handleNewUserCreated()");
+ }
if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -9867,12 +9928,24 @@
}
private void handleNewUserCreated(UserInfo user) {
- if (!mOwners.hasDeviceOwner()) return;
+ if (VERBOSE_LOG) Slog.v(LOG_TAG, "handleNewUserCreated(): " + user.toFullString());
+
+ if (!mOwners.hasDeviceOwner() || !user.isFull() || user.isManagedProfile()) return;
final int userId = user.id;
- Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer");
- setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED);
+ // TODO(b/177547285): add CTS test
+ if (mInjector.userManagerIsHeadlessSystemUserMode()) {
+ ComponentName admin = mOwners.getDeviceOwnerComponent();
+ Slog.i(LOG_TAG, "Automatically setting profile owner (" + admin + ") on new user "
+ + userId);
+ manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin,
+ /* managedUser= */ userId, /* adminExtras= */ null,
+ /* showDisclaimer= */ true);
+ } else {
+ Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer");
+ setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED);
+ }
}
@Override
@@ -11369,6 +11442,7 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_MASTER_VOLUME_MUTED);
synchronized (getLockObject()) {
setUserRestriction(who, UserManager.DISALLOW_UNMUTE_DEVICE, on, /* parent */ false);
@@ -12007,8 +12081,13 @@
}
@Override
- public ComponentName getProfileOwnerAsUser(int userHandle) {
- return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle);
+ public ComponentName getProfileOwnerAsUser(@UserIdInt int userId) {
+ return DevicePolicyManagerService.this.getProfileOwnerAsUser(userId);
+ }
+
+ @Override
+ public int getDeviceOwnerUserId() {
+ return DevicePolicyManagerService.this.getDeviceOwnerUserId();
}
@Override
@@ -12340,6 +12419,7 @@
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PERMISSION_POLICY);
synchronized (getLockObject()) {
DevicePolicyData userPolicy = getUserData(caller.getUserId());
@@ -12375,6 +12455,7 @@
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PERMISSION_GRANT_STATE);
synchronized (getLockObject()) {
long ident = mInjector.binderClearCallingIdentity();
@@ -14351,6 +14432,7 @@
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_CLEAR_APPLICATION_USER_DATA);
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -14382,6 +14464,7 @@
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOGOUT_ENABLED);
synchronized (getLockObject()) {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
@@ -14749,6 +14832,8 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_OVERRIDE_APNS_ENABLED);
+
setOverrideApnsEnabledUnchecked(enabled);
}
@@ -14850,6 +14935,7 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_GLOBAL_PRIVATE_DNS);
switch (mode) {
case PRIVATE_DNS_MODE_OPPORTUNISTIC:
@@ -14922,6 +15008,7 @@
final CallerIdentity caller = getCallerIdentity(admin);
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_INSTALL_SYSTEM_UPDATE);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.INSTALL_SYSTEM_UPDATE)
@@ -15749,14 +15836,15 @@
}
@Override
- public String getEnrollmentSpecificId() {
+ public String getEnrollmentSpecificId(String callerPackage) {
if (!mHasFeature) {
return "";
}
- final CallerIdentity caller = getCallerIdentity();
+ final CallerIdentity caller = getCallerIdentity(callerPackage);
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwner(caller));
+ isDeviceOwner(caller) || isProfileOwner(caller)
+ || isCallerDelegate(caller, DELEGATION_CERT_INSTALL));
synchronized (getLockObject()) {
final ActiveAdmin requiredAdmin = getDeviceOrProfileOwnerAdminLocked(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 79a82b8..809afe0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -31,6 +31,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.IndentingPrintWriter;
import android.util.Log;
@@ -203,6 +204,7 @@
}
pushToPackageManagerLocked();
pushToActivityTaskManagerLocked();
+ pushToActivityManagerLocked();
pushToAppOpsLocked();
}
}
@@ -218,12 +220,34 @@
}
private void pushToActivityTaskManagerLocked() {
- final int uid = mDeviceOwner != null ? mPackageManagerInternal.getPackageUid(
- mDeviceOwner.packageName,
- PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES, mDeviceOwnerUserId)
- : Process.INVALID_UID;
- mActivityTaskManagerInternal.setDeviceOwnerUid(uid);
- mActivityManagerInternal.setDeviceOwnerUid(uid);
+ mActivityTaskManagerInternal.setDeviceOwnerUid(getDeviceOwnerUidLocked());
+ }
+
+ private void pushToActivityManagerLocked() {
+ mActivityManagerInternal.setDeviceOwnerUid(getDeviceOwnerUidLocked());
+
+ final ArraySet<Integer> profileOwners = new ArraySet<>();
+ for (int poi = mProfileOwners.size() - 1; poi >= 0; poi--) {
+ final int userId = mProfileOwners.keyAt(poi);
+ final int profileOwnerUid = mPackageManagerInternal.getPackageUid(
+ mProfileOwners.valueAt(poi).packageName,
+ PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES,
+ userId);
+ if (profileOwnerUid >= 0) {
+ profileOwners.add(profileOwnerUid);
+ }
+ }
+ mActivityManagerInternal.setProfileOwnerUid(profileOwners);
+ }
+
+ int getDeviceOwnerUidLocked() {
+ if (mDeviceOwner != null) {
+ return mPackageManagerInternal.getPackageUid(mDeviceOwner.packageName,
+ PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES,
+ mDeviceOwnerUserId);
+ } else {
+ return Process.INVALID_UID;
+ }
}
String getDeviceOwnerPackageName() {
@@ -301,6 +325,7 @@
mUserManagerInternal.setDeviceManaged(true);
pushToPackageManagerLocked();
pushToActivityTaskManagerLocked();
+ pushToActivityManagerLocked();
pushToAppOpsLocked();
}
}
@@ -313,6 +338,7 @@
mUserManagerInternal.setDeviceManaged(false);
pushToPackageManagerLocked();
pushToActivityTaskManagerLocked();
+ pushToActivityManagerLocked();
pushToAppOpsLocked();
}
}
@@ -325,6 +351,7 @@
/* remoteBugreportHash =*/ null, /* isOrganizationOwnedDevice =*/ false));
mUserManagerInternal.setUserManaged(userId, true);
pushToPackageManagerLocked();
+ pushToActivityManagerLocked();
pushToAppOpsLocked();
}
}
@@ -334,6 +361,7 @@
mProfileOwners.remove(userId);
mUserManagerInternal.setUserManaged(userId, false);
pushToPackageManagerLocked();
+ pushToActivityManagerLocked();
pushToAppOpsLocked();
}
}
@@ -347,6 +375,7 @@
ownerInfo.isOrganizationOwnedDevice);
mProfileOwners.put(userId, newOwnerInfo);
pushToPackageManagerLocked();
+ pushToActivityManagerLocked();
pushToAppOpsLocked();
}
}
@@ -361,6 +390,7 @@
mDeviceOwner.isOrganizationOwnedDevice);
pushToPackageManagerLocked();
pushToActivityTaskManagerLocked();
+ pushToActivityManagerLocked();
pushToAppOpsLocked();
}
}
@@ -665,9 +695,7 @@
try {
final SparseIntArray owners = new SparseIntArray();
if (mDeviceOwner != null) {
- final int uid = mPackageManagerInternal.getPackageUid(mDeviceOwner.packageName,
- PackageManager.MATCH_ALL | PackageManager.MATCH_KNOWN_PACKAGES,
- mDeviceOwnerUserId);
+ final int uid = getDeviceOwnerUidLocked();
if (uid >= 0) {
owners.put(mDeviceOwnerUserId, uid);
}
@@ -695,6 +723,7 @@
public void systemReady() {
synchronized (mLock) {
mSystemReady = true;
+ pushToActivityManagerLocked();
pushToAppOpsLocked();
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index f8cbc35..57b3e8d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -23,6 +23,8 @@
import static android.os.IServiceManager.DUMP_FLAG_PROTO;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myPid;
+import static android.system.OsConstants.O_CLOEXEC;
+import static android.system.OsConstants.O_RDONLY;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.utils.TimingsTraceAndSlog.SYSTEM_SERVER_TIMING_TAG;
@@ -77,6 +79,8 @@
import android.provider.Settings;
import android.server.ServerProtoEnums;
import android.sysprop.VoldProperties;
+import android.system.ErrnoException;
+import android.system.Os;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
@@ -156,7 +160,7 @@
import com.android.server.pm.dex.SystemServerDexLoadReporter;
import com.android.server.policy.PermissionPolicyService;
import com.android.server.policy.PhoneWindowManager;
-import com.android.server.policy.role.LegacyRoleResolutionPolicy;
+import com.android.server.policy.role.LegacyRoleStateProviderImpl;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.power.ThermalManagerService;
@@ -429,11 +433,71 @@
*/
private static native void initZygoteChildHeapProfiling();
+ private static final String SYSPROP_FDTRACK_ENABLE_THRESHOLD =
+ "persist.sys.debug.fdtrack_enable_threshold";
+ private static final String SYSPROP_FDTRACK_ABORT_THRESHOLD =
+ "persist.sys.debug.fdtrack_abort_threshold";
+ private static final String SYSPROP_FDTRACK_INTERVAL =
+ "persist.sys.debug.fdtrack_interval";
+
+ private static int getMaxFd() {
+ FileDescriptor fd = null;
+ try {
+ fd = Os.open("/dev/null", O_RDONLY | O_CLOEXEC, 0);
+ return fd.getInt$();
+ } catch (ErrnoException ex) {
+ Slog.e("System", "Failed to get maximum fd: " + ex);
+ } finally {
+ if (fd != null) {
+ try {
+ Os.close(fd);
+ } catch (ErrnoException ex) {
+ // If Os.close threw, something went horribly wrong.
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ return Integer.MAX_VALUE;
+ }
+
+ private static native void fdtrackAbort();
/**
* Spawn a thread that monitors for fd leaks.
*/
- private static native void spawnFdLeakCheckThread();
+ private static void spawnFdLeakCheckThread() {
+ final int enableThreshold = SystemProperties.getInt(SYSPROP_FDTRACK_ENABLE_THRESHOLD, 1024);
+ final int abortThreshold = SystemProperties.getInt(SYSPROP_FDTRACK_ABORT_THRESHOLD, 2048);
+ final int checkInterval = SystemProperties.getInt(SYSPROP_FDTRACK_INTERVAL, 120);
+
+ new Thread(() -> {
+ boolean enabled = false;
+ while (true) {
+ int maxFd = getMaxFd();
+ if (maxFd > enableThreshold) {
+ // Do a manual GC to clean up fds that are hanging around as garbage.
+ System.gc();
+ maxFd = getMaxFd();
+ }
+
+ if (maxFd > enableThreshold && !enabled) {
+ Slog.i("System", "fdtrack enable threshold reached, enabling");
+ System.loadLibrary("fdtrack");
+ enabled = true;
+ } else if (maxFd > abortThreshold) {
+ Slog.i("System", "fdtrack abort threshold reached, dumping and aborting");
+ fdtrackAbort();
+ }
+
+ try {
+ Thread.sleep(checkInterval);
+ } catch (InterruptedException ex) {
+ continue;
+ }
+ }
+ }).start();
+ }
/**
* Start native Incremental Service and get its handle.
@@ -1957,7 +2021,7 @@
// Grants default permissions and defines roles
t.traceBegin("StartRoleManagerService");
mSystemServiceManager.startService(new RoleManagerService(
- mSystemContext, new LegacyRoleResolutionPolicy(mSystemContext)));
+ mSystemContext, new LegacyRoleStateProviderImpl(mSystemContext)));
t.traceEnd();
// We need to always start this service, regardless of whether the
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 16b9165..091e688 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -188,6 +188,9 @@
ConversationStatus status) {
handleIncomingUser(userId);
checkCallerIsSameApp(packageName);
+ if (status.getStartTimeMillis() > System.currentTimeMillis()) {
+ throw new IllegalArgumentException("Start time must be in the past");
+ }
mDataManager.addOrUpdateStatus(packageName, userId, conversationId, status);
}
diff --git a/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java b/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
index e4daddc..0a85f7f 100644
--- a/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
+++ b/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
@@ -85,8 +85,10 @@
}
@WorkerThread
- synchronized void delete(@NonNull String fileName) {
- mScheduledFileDataMap.remove(fileName);
+ void delete(@NonNull String fileName) {
+ synchronized (this) {
+ mScheduledFileDataMap.remove(fileName);
+ }
final File file = getFile(fileName);
if (!file.exists()) {
return;
@@ -136,28 +138,6 @@
}
/**
- * Reads all files in directory and returns a map with file names as keys and parsed file
- * contents as values.
- */
- @WorkerThread
- @Nullable
- Map<String, T> readAll() {
- File[] files = mRootDir.listFiles(File::isFile);
- if (files == null) {
- return null;
- }
-
- Map<String, T> results = new ArrayMap<>();
- for (File file : files) {
- T result = parseFile(file);
- if (result != null) {
- results.put(file.getName(), result);
- }
- }
- return results;
- }
-
- /**
* Schedules the specified data to be flushed to a file in the future. Subsequent
* calls for the same file before the flush occurs will replace the previous data but will not
* reset when the flush will occur. All unique files will be flushed at the same time.
diff --git a/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
new file mode 100644
index 0000000..c631026
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.people.data;
+
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.app.people.ConversationStatus;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.CancellationSignal;
+import android.os.SystemClock;
+
+import com.android.server.LocalServices;
+import com.android.server.notification.NotificationRecord;
+import com.android.server.people.PeopleServiceInternal;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * If a {@link ConversationStatus} is added to the system with an expiration time, remove that
+ * status at that time
+ */
+public class ConversationStatusExpirationBroadcastReceiver extends BroadcastReceiver {
+
+ static final String ACTION = "ConversationStatusExpiration";
+ static final String EXTRA_USER_ID = "userId";
+ static final int REQUEST_CODE = 10;
+ static final String SCHEME = "expStatus";
+
+ void scheduleExpiration(Context context, @UserIdInt int userId, String pkg,
+ String conversationId, ConversationStatus status) {
+
+ final PendingIntent pi = PendingIntent.getBroadcast(context,
+ REQUEST_CODE,
+ new Intent(ACTION)
+ .setData(new Uri.Builder().scheme(SCHEME)
+ .appendPath(getKey(userId, pkg, conversationId, status))
+ .build())
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+ .putExtra(EXTRA_USER_ID, userId),
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ context.getSystemService(AlarmManager.class).setExactAndAllowWhileIdle(
+ AlarmManager.RTC_WAKEUP, status.getEndTimeMillis(), pi);
+ }
+
+ private static String getKey(@UserIdInt int userId, String pkg,
+ String conversationId, ConversationStatus status) {
+ return userId + pkg + conversationId + status.getId();
+ }
+
+ static IntentFilter getFilter() {
+ IntentFilter conversationStatusFilter =
+ new IntentFilter(ConversationStatusExpirationBroadcastReceiver.ACTION);
+ conversationStatusFilter.addDataScheme(
+ ConversationStatusExpirationBroadcastReceiver.SCHEME);
+ return conversationStatusFilter;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+ if (ACTION.equals(action)) {
+ new Thread(() -> {
+ PeopleServiceInternal peopleServiceInternal =
+ LocalServices.getService(PeopleServiceInternal.class);
+ peopleServiceInternal.pruneDataForUser(intent.getIntExtra(EXTRA_USER_ID,
+ ActivityManager.getCurrentUser()), new CancellationSignal());
+ }).start();
+ }
+ }
+}
diff --git a/services/people/java/com/android/server/people/data/ConversationStore.java b/services/people/java/com/android/server/people/data/ConversationStore.java
index 28e3d4b..6faeb80 100644
--- a/services/people/java/com/android/server/people/data/ConversationStore.java
+++ b/services/people/java/com/android/server/people/data/ConversationStore.java
@@ -90,7 +90,7 @@
* after the device powers on and the user has been unlocked.
*/
@WorkerThread
- synchronized void loadConversationsFromDisk() {
+ void loadConversationsFromDisk() {
ConversationInfosProtoDiskReadWriter conversationInfosProtoDiskReadWriter =
getConversationInfosProtoDiskReadWriter();
if (conversationInfosProtoDiskReadWriter == null) {
@@ -111,54 +111,64 @@
* powering off.
*/
@MainThread
- synchronized void saveConversationsToDisk() {
+ void saveConversationsToDisk() {
ConversationInfosProtoDiskReadWriter conversationInfosProtoDiskReadWriter =
getConversationInfosProtoDiskReadWriter();
if (conversationInfosProtoDiskReadWriter != null) {
- conversationInfosProtoDiskReadWriter.saveConversationsImmediately(
- new ArrayList<>(mConversationInfoMap.values()));
+ List<ConversationInfo> conversations;
+ synchronized (this) {
+ conversations = new ArrayList<>(mConversationInfoMap.values());
+ }
+ conversationInfosProtoDiskReadWriter.saveConversationsImmediately(conversations);
}
}
@MainThread
- synchronized void addOrUpdate(@NonNull ConversationInfo conversationInfo) {
+ void addOrUpdate(@NonNull ConversationInfo conversationInfo) {
updateConversationsInMemory(conversationInfo);
scheduleUpdateConversationsOnDisk();
}
@MainThread
@Nullable
- synchronized ConversationInfo deleteConversation(@NonNull String shortcutId) {
- ConversationInfo conversationInfo = mConversationInfoMap.remove(shortcutId);
- if (conversationInfo == null) {
- return null;
- }
+ ConversationInfo deleteConversation(@NonNull String shortcutId) {
+ ConversationInfo conversationInfo;
+ synchronized (this) {
+ conversationInfo = mConversationInfoMap.remove(shortcutId);
+ if (conversationInfo == null) {
+ return null;
+ }
- LocusId locusId = conversationInfo.getLocusId();
- if (locusId != null) {
- mLocusIdToShortcutIdMap.remove(locusId);
- }
+ LocusId locusId = conversationInfo.getLocusId();
+ if (locusId != null) {
+ mLocusIdToShortcutIdMap.remove(locusId);
+ }
- Uri contactUri = conversationInfo.getContactUri();
- if (contactUri != null) {
- mContactUriToShortcutIdMap.remove(contactUri);
- }
+ Uri contactUri = conversationInfo.getContactUri();
+ if (contactUri != null) {
+ mContactUriToShortcutIdMap.remove(contactUri);
+ }
- String phoneNumber = conversationInfo.getContactPhoneNumber();
- if (phoneNumber != null) {
- mPhoneNumberToShortcutIdMap.remove(phoneNumber);
- }
+ String phoneNumber = conversationInfo.getContactPhoneNumber();
+ if (phoneNumber != null) {
+ mPhoneNumberToShortcutIdMap.remove(phoneNumber);
+ }
- String notifChannelId = conversationInfo.getNotificationChannelId();
- if (notifChannelId != null) {
- mNotifChannelIdToShortcutIdMap.remove(notifChannelId);
+ String notifChannelId = conversationInfo.getNotificationChannelId();
+ if (notifChannelId != null) {
+ mNotifChannelIdToShortcutIdMap.remove(notifChannelId);
+ }
}
scheduleUpdateConversationsOnDisk();
return conversationInfo;
}
- synchronized void forAllConversations(@NonNull Consumer<ConversationInfo> consumer) {
- for (ConversationInfo ci : mConversationInfoMap.values()) {
+ void forAllConversations(@NonNull Consumer<ConversationInfo> consumer) {
+ List<ConversationInfo> conversations;
+ synchronized (this) {
+ conversations = new ArrayList<>(mConversationInfoMap.values());
+ }
+ for (ConversationInfo ci : conversations) {
consumer.accept(ci);
}
}
@@ -184,16 +194,19 @@
}
@Nullable
- ConversationInfo getConversationByNotificationChannelId(@NonNull String notifChannelId) {
+ synchronized ConversationInfo getConversationByNotificationChannelId(
+ @NonNull String notifChannelId) {
return getConversation(mNotifChannelIdToShortcutIdMap.get(notifChannelId));
}
- synchronized void onDestroy() {
- mConversationInfoMap.clear();
- mContactUriToShortcutIdMap.clear();
- mLocusIdToShortcutIdMap.clear();
- mNotifChannelIdToShortcutIdMap.clear();
- mPhoneNumberToShortcutIdMap.clear();
+ void onDestroy() {
+ synchronized (this) {
+ mConversationInfoMap.clear();
+ mContactUriToShortcutIdMap.clear();
+ mLocusIdToShortcutIdMap.clear();
+ mNotifChannelIdToShortcutIdMap.clear();
+ mPhoneNumberToShortcutIdMap.clear();
+ }
ConversationInfosProtoDiskReadWriter writer = getConversationInfosProtoDiskReadWriter();
if (writer != null) {
writer.deleteConversationsFile();
@@ -201,22 +214,21 @@
}
@Nullable
- synchronized byte[] getBackupPayload() {
+ byte[] getBackupPayload() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream conversationInfosOut = new DataOutputStream(baos);
- for (ConversationInfo conversationInfo : mConversationInfoMap.values()) {
+ forAllConversations(conversationInfo -> {
byte[] backupPayload = conversationInfo.getBackupPayload();
if (backupPayload == null) {
- continue;
+ return;
}
try {
conversationInfosOut.writeInt(backupPayload.length);
conversationInfosOut.write(backupPayload);
} catch (IOException e) {
Slog.e(TAG, "Failed to write conversation info to backup payload.", e);
- return null;
}
- }
+ });
try {
conversationInfosOut.writeInt(CONVERSATION_INFOS_END_TOKEN);
} catch (IOException e) {
@@ -226,7 +238,7 @@
return baos.toByteArray();
}
- synchronized void restore(@NonNull byte[] payload) {
+ void restore(@NonNull byte[] payload) {
DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload));
try {
for (int conversationInfoSize = in.readInt();
@@ -245,7 +257,6 @@
}
}
- @MainThread
private synchronized void updateConversationsInMemory(
@NonNull ConversationInfo conversationInfo) {
mConversationInfoMap.put(conversationInfo.getShortcutId(), conversationInfo);
@@ -273,12 +284,15 @@
/** Schedules a dump of all conversations onto disk, overwriting existing values. */
@MainThread
- private synchronized void scheduleUpdateConversationsOnDisk() {
+ private void scheduleUpdateConversationsOnDisk() {
ConversationInfosProtoDiskReadWriter conversationInfosProtoDiskReadWriter =
getConversationInfosProtoDiskReadWriter();
if (conversationInfosProtoDiskReadWriter != null) {
- conversationInfosProtoDiskReadWriter.scheduleConversationsSave(
- new ArrayList<>(mConversationInfoMap.values()));
+ List<ConversationInfo> conversations;
+ synchronized (this) {
+ conversations = new ArrayList<>(mConversationInfoMap.values());
+ }
+ conversationInfosProtoDiskReadWriter.scheduleConversationsSave(conversations);
}
}
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index e04e287..7521415 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -124,6 +124,7 @@
private PackageManagerInternal mPackageManagerInternal;
private NotificationManagerInternal mNotificationManagerInternal;
private UserManager mUserManager;
+ private ConversationStatusExpirationBroadcastReceiver mStatusExpReceiver;
public DataManager(Context context) {
this(context, new Injector());
@@ -145,6 +146,10 @@
mShortcutServiceInternal.addShortcutChangeCallback(new ShortcutServiceCallback());
+ mStatusExpReceiver = new ConversationStatusExpirationBroadcastReceiver();
+ mContext.registerReceiver(mStatusExpReceiver,
+ ConversationStatusExpirationBroadcastReceiver.getFilter());
+
IntentFilter shutdownIntentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
BroadcastReceiver shutdownBroadcastReceiver = new ShutdownBroadcastReceiver();
mContext.registerReceiver(shutdownBroadcastReceiver, shutdownIntentFilter);
@@ -296,6 +301,27 @@
}
/**
+ * Removes any status with an expiration time in the past.
+ */
+ public void pruneExpiredConversationStatuses(@UserIdInt int callingUserId, long currentTimeMs) {
+ forPackagesInProfile(callingUserId, packageData -> {
+ final ConversationStore cs = packageData.getConversationStore();
+ packageData.forAllConversations(conversationInfo -> {
+ ConversationInfo.Builder builder = new ConversationInfo.Builder(conversationInfo);
+ List<ConversationStatus> newStatuses = new ArrayList<>();
+ for (ConversationStatus status : conversationInfo.getStatuses()) {
+ if (status.getEndTimeMillis() < 0
+ || currentTimeMs < status.getEndTimeMillis()) {
+ newStatuses.add(status);
+ }
+ }
+ builder.setStatuses(newStatuses);
+ cs.addOrUpdate(builder.build());
+ });
+ });
+ }
+
+ /**
* Returns the last notification interaction with the specified conversation. If the
* conversation can't be found or no interactions have been recorded, returns 0L.
*/
@@ -317,6 +343,12 @@
ConversationInfo.Builder builder = new ConversationInfo.Builder(convToModify);
builder.addOrUpdateStatus(status);
cs.addOrUpdate(builder.build());
+
+ if (status.getEndTimeMillis() >= 0) {
+ mStatusExpReceiver.scheduleExpiration(
+ mContext, userId, packageName, conversationId, status);
+ }
+
}
public void clearStatus(String packageName, int userId, String conversationId,
@@ -458,6 +490,7 @@
packageData.getEventStore().deleteEventHistories(EventStore.CATEGORY_SMS);
}
packageData.pruneOrphanEvents();
+ pruneExpiredConversationStatuses(userId, System.currentTimeMillis());
pruneOldRecentConversations(userId, System.currentTimeMillis());
cleanupCachedShortcuts(userId, MAX_CACHED_RECENT_SHORTCUTS);
});
diff --git a/services/searchui/OWNERS b/services/searchui/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/services/searchui/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt
index 6de3d4e..23ed278 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/src/com/android/server/pm/test/intent/verifier/VerifyReceiverTest.kt
@@ -77,12 +77,14 @@
val filter = IntentFilter().apply {
addAction(Intent.ACTION_VIEW)
addCategory(Intent.CATEGORY_DEFAULT)
+ addCategory(Intent.CATEGORY_BROWSABLE)
addDataScheme(uri.scheme)
addDataAuthority(uri.authority, null)
}
val intent = Intent(Intent.ACTION_VIEW, uri).apply {
addCategory(Intent.CATEGORY_DEFAULT)
+ addCategory(Intent.CATEGORY_BROWSABLE)
}
val allResults = context.packageManager.queryIntentActivities(intent, 0)
val allComponents = allResults
@@ -132,6 +134,8 @@
val intent = Intent(Intent.ACTION_VIEW).apply {
data = uri
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ addCategory(Intent.CATEGORY_DEFAULT)
+ addCategory(Intent.CATEGORY_BROWSABLE)
}
val expectedActivities = params.expected.toMutableList()
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 4740df5..8099eda 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -602,7 +602,7 @@
}
private void answerNetwork(int uid, Network net, NetworkCapabilities caps) {
- when(mConnManager.getActiveNetworkForUid(eq(uid))).thenReturn(net);
+ when(mConnManager.getActiveNetworkForUid(eq(uid), anyBoolean())).thenReturn(net);
when(mConnManager.getNetworkCapabilities(eq(net))).thenReturn(caps);
if (net != null) {
final NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, null, null);
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java b/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
index 675274b..69fe140 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/gnss/hal/FakeGnssHal.java
@@ -233,6 +233,7 @@
private boolean mAntennaInfoListeningStarted = false;
private boolean mMeasurementCollectionStarted = false;
private boolean mMeasurementCollectionFullTracking = false;
+ private boolean mMeasurementCollectionCorrVecOutputsEnabled = false;
private GnssHalPositionMode mPositionMode = new GnssHalPositionMode();
private GnssHalBatchingMode mBatchingMode = new GnssHalBatchingMode();
private final ArrayList<Location> mBatchedLocations = new ArrayList<>();
@@ -521,9 +522,11 @@
}
@Override
- protected boolean startMeasurementCollection(boolean enableFullTracking) {
+ protected boolean startMeasurementCollection(boolean enableFullTracking,
+ boolean enableCorrVecOutputs) {
mState.mMeasurementCollectionStarted = true;
mState.mMeasurementCollectionFullTracking = enableFullTracking;
+ mState.mMeasurementCollectionCorrVecOutputsEnabled = enableCorrVecOutputs;
return true;
}
@@ -531,6 +534,7 @@
protected boolean stopMeasurementCollection() {
mState.mMeasurementCollectionStarted = false;
mState.mMeasurementCollectionFullTracking = false;
+ mState.mMeasurementCollectionCorrVecOutputsEnabled = false;
return true;
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 839bc93..df8a720 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -67,7 +67,7 @@
private static final String INTENT_ACTION = "TESTACTION";
private static final String DESCRIPTION = "description";
private static final PendingIntent TEST_PENDING_INTENT = PendingIntent.getBroadcast(
- InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION), 0);
+ InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION), PendingIntent.FLAG_MUTABLE_UNAUDITED);
private static final RemoteAction TEST_ACTION = new RemoteAction(
Icon.createWithContentUri("content://test"),
LABEL,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
index 98f4764..8b6b7c2 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
@@ -76,14 +76,14 @@
private static final String DESCRIPTION1 = "description1";
private static final String DESCRIPTION2 = "description2";
private static final PendingIntent TEST_PENDING_INTENT_1 = PendingIntent.getBroadcast(
- InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION1), 0);
+ InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION1), PendingIntent.FLAG_MUTABLE_UNAUDITED);
private static final RemoteAction NEW_TEST_ACTION_1 = new RemoteAction(
Icon.createWithContentUri("content://test"),
LABEL_1,
DESCRIPTION1,
TEST_PENDING_INTENT_1);
private static final PendingIntent TEST_PENDING_INTENT_2 = PendingIntent.getBroadcast(
- InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION2), 0);
+ InstrumentationRegistry.getTargetContext(), 0, new Intent(INTENT_ACTION2), PendingIntent.FLAG_MUTABLE_UNAUDITED);
private static final RemoteAction NEW_TEST_ACTION_2 = new RemoteAction(
Icon.createWithContentUri("content://test"),
LABEL_2,
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index c6fde87..009cb0b 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -22,13 +22,13 @@
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
+import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.SearchResult;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.app.appsearch.exceptions.AppSearchException;
import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
-import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter;
import com.android.server.appsearch.proto.DocumentProto;
import com.android.server.appsearch.proto.GetOptimizeInfoResultProto;
import com.android.server.appsearch.proto.PropertyConfigProto;
@@ -41,6 +41,7 @@
import com.android.server.appsearch.proto.TermMatchType;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
@@ -55,27 +56,10 @@
public class AppSearchImplTest {
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
private AppSearchImpl mAppSearchImpl;
- private SchemaTypeConfigProto mVisibilitySchemaProto;
@Before
public void setUp() throws Exception {
mAppSearchImpl = AppSearchImpl.create(mTemporaryFolder.newFolder());
-
- AppSearchSchema visibilitySchema = VisibilityStore.SCHEMA;
-
- // We need to rewrite the schema type to follow AppSearchImpl's prefixing scheme.
- AppSearchSchema.Builder rewrittenVisibilitySchema =
- new AppSearchSchema.Builder(
- AppSearchImpl.createPrefix(
- VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME)
- + VisibilityStore.SCHEMA_TYPE);
- List<AppSearchSchema.PropertyConfig> visibilityProperties =
- visibilitySchema.getProperties();
- for (AppSearchSchema.PropertyConfig property : visibilityProperties) {
- rewrittenVisibilitySchema.addProperty(property);
- }
- mVisibilitySchemaProto =
- SchemaToProtoConverter.toSchemaTypeConfigProto(rewrittenVisibilitySchema.build());
}
// TODO(b/175430168) add test to verify reset is working properly.
@@ -407,6 +391,7 @@
"database",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
// Insert enough documents.
@@ -464,6 +449,7 @@
"database",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
// Insert document
@@ -495,12 +481,14 @@
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
mAppSearchImpl.setSchema(
"package",
"database2",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
// Insert documents
@@ -537,6 +525,117 @@
assertThat(searchResultPage.getResults()).isEmpty();
}
+ /**
+ * TODO(b/169883602): This should be an integration test at the cts-level. This is a short-term
+ * test until we have official support for multiple-apps indexing at once.
+ */
+ @Test
+ public void testQueryWithMultiplePackages_noPackageFilters() throws Exception {
+ // Insert package1 schema
+ List<AppSearchSchema> schema1 =
+ ImmutableList.of(new AppSearchSchema.Builder("schema1").build());
+ mAppSearchImpl.setSchema(
+ "package1",
+ "database1",
+ schema1,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+
+ // Insert package2 schema
+ List<AppSearchSchema> schema2 =
+ ImmutableList.of(new AppSearchSchema.Builder("schema2").build());
+ mAppSearchImpl.setSchema(
+ "package2",
+ "database2",
+ schema2,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+
+ // Insert package1 document
+ GenericDocument document =
+ new GenericDocument.Builder<>("uri", "schema1").setNamespace("namespace").build();
+ mAppSearchImpl.putDocument("package1", "database1", document);
+
+ // No query filters specified, package2 shouldn't be able to query for package1's documents.
+ SearchSpec searchSpec =
+ new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
+ SearchResultPage searchResultPage =
+ mAppSearchImpl.query("package2", "database2", "", searchSpec);
+ assertThat(searchResultPage.getResults()).isEmpty();
+
+ // Insert package2 document
+ document =
+ new GenericDocument.Builder<>("uri", "schema2").setNamespace("namespace").build();
+ mAppSearchImpl.putDocument("package2", "database2", document);
+
+ // No query filters specified. package2 should only get its own documents back.
+ searchResultPage = mAppSearchImpl.query("package2", "database2", "", searchSpec);
+ assertThat(searchResultPage.getResults()).hasSize(1);
+ assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document);
+ }
+
+ /**
+ * TODO(b/169883602): This should be an integration test at the cts-level. This is a short-term
+ * test until we have official support for multiple-apps indexing at once.
+ */
+ @Test
+ public void testQueryWithMultiplePackages_withPackageFilters() throws Exception {
+ // Insert package1 schema
+ List<AppSearchSchema> schema1 =
+ ImmutableList.of(new AppSearchSchema.Builder("schema1").build());
+ mAppSearchImpl.setSchema(
+ "package1",
+ "database1",
+ schema1,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+
+ // Insert package2 schema
+ List<AppSearchSchema> schema2 =
+ ImmutableList.of(new AppSearchSchema.Builder("schema2").build());
+ mAppSearchImpl.setSchema(
+ "package2",
+ "database2",
+ schema2,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+
+ // Insert package1 document
+ GenericDocument document =
+ new GenericDocument.Builder<>("uri", "schema1").setNamespace("namespace").build();
+ mAppSearchImpl.putDocument("package1", "database1", document);
+
+ // "package1" filter specified, but package2 shouldn't be able to query for package1's
+ // documents.
+ SearchSpec searchSpec =
+ new SearchSpec.Builder()
+ .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
+ .addFilterPackageNames("package1")
+ .build();
+ SearchResultPage searchResultPage =
+ mAppSearchImpl.query("package2", "database2", "", searchSpec);
+ assertThat(searchResultPage.getResults()).isEmpty();
+
+ // Insert package2 document
+ document =
+ new GenericDocument.Builder<>("uri", "schema2").setNamespace("namespace").build();
+ mAppSearchImpl.putDocument("package2", "database2", document);
+
+ // "package2" filter specified, package2 should only get its own documents back.
+ searchSpec =
+ new SearchSpec.Builder()
+ .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
+ .addFilterPackageNames("package2")
+ .build();
+ searchResultPage = mAppSearchImpl.query("package2", "database2", "", searchSpec);
+ assertThat(searchResultPage.getResults()).hasSize(1);
+ assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document);
+ }
+
@Test
public void testGlobalQueryEmptyDatabase() throws Exception {
SearchSpec searchSpec =
@@ -545,6 +644,115 @@
assertThat(searchResultPage.getResults()).isEmpty();
}
+ /**
+ * TODO(b/169883602): This should be an integration test at the cts-level. This is a short-term
+ * test until we have official support for multiple-apps indexing at once.
+ */
+ @Test
+ public void testGlobalQueryWithMultiplePackages_noPackageFilters() throws Exception {
+ // Insert package1 schema
+ List<AppSearchSchema> schema1 =
+ ImmutableList.of(new AppSearchSchema.Builder("schema1").build());
+ mAppSearchImpl.setSchema(
+ "package1",
+ "database1",
+ schema1,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+
+ // Insert package2 schema
+ List<AppSearchSchema> schema2 =
+ ImmutableList.of(new AppSearchSchema.Builder("schema2").build());
+ mAppSearchImpl.setSchema(
+ "package2",
+ "database2",
+ schema2,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+
+ // Insert package1 document
+ GenericDocument document1 =
+ new GenericDocument.Builder<>("uri", "schema1").setNamespace("namespace").build();
+ mAppSearchImpl.putDocument("package1", "database1", document1);
+
+ // Insert package2 document
+ GenericDocument document2 =
+ new GenericDocument.Builder<>("uri", "schema2").setNamespace("namespace").build();
+ mAppSearchImpl.putDocument("package2", "database2", document2);
+
+ // No query filters specified, global query can retrieve all documents.
+ SearchSpec searchSpec =
+ new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
+ SearchResultPage searchResultPage = mAppSearchImpl.globalQuery("", searchSpec);
+ assertThat(searchResultPage.getResults()).hasSize(2);
+
+ // Document2 will be first since it got indexed later and has a "better", aka more recent
+ // score.
+ assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document2);
+ assertThat(searchResultPage.getResults().get(1).getDocument()).isEqualTo(document1);
+ }
+
+ /**
+ * TODO(b/169883602): This should be an integration test at the cts-level. This is a short-term
+ * test until we have official support for multiple-apps indexing at once.
+ */
+ @Test
+ public void testGlobalQueryWithMultiplePackages_withPackageFilters() throws Exception {
+ // Insert package1 schema
+ List<AppSearchSchema> schema1 =
+ ImmutableList.of(new AppSearchSchema.Builder("schema1").build());
+ mAppSearchImpl.setSchema(
+ "package1",
+ "database1",
+ schema1,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+
+ // Insert package2 schema
+ List<AppSearchSchema> schema2 =
+ ImmutableList.of(new AppSearchSchema.Builder("schema2").build());
+ mAppSearchImpl.setSchema(
+ "package2",
+ "database2",
+ schema2,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+
+ // Insert package1 document
+ GenericDocument document1 =
+ new GenericDocument.Builder<>("uri", "schema1").setNamespace("namespace").build();
+ mAppSearchImpl.putDocument("package1", "database1", document1);
+
+ // Insert package2 document
+ GenericDocument document2 =
+ new GenericDocument.Builder<>("uri", "schema2").setNamespace("namespace").build();
+ mAppSearchImpl.putDocument("package2", "database2", document2);
+
+ // "package1" filter specified
+ SearchSpec searchSpec =
+ new SearchSpec.Builder()
+ .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
+ .addFilterPackageNames("package1")
+ .build();
+ SearchResultPage searchResultPage = mAppSearchImpl.globalQuery("", searchSpec);
+ assertThat(searchResultPage.getResults()).hasSize(1);
+ assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document1);
+
+ // "package2" filter specified
+ searchSpec =
+ new SearchSpec.Builder()
+ .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
+ .addFilterPackageNames("package2")
+ .build();
+ searchResultPage = mAppSearchImpl.globalQuery("", searchSpec);
+ assertThat(searchResultPage.getResults()).hasSize(1);
+ assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document2);
+ }
+
@Test
public void testRemoveEmptyDatabase_noExceptionThrown() throws Exception {
SearchSpec searchSpec =
@@ -567,6 +775,9 @@
@Test
public void testSetSchema() throws Exception {
+ List<SchemaTypeConfigProto> existingSchemas =
+ mAppSearchImpl.getSchemaProtoLocked().getTypesList();
+
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("Email").build());
// Set schema Email to AppSearch database1
@@ -575,6 +786,7 @@
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
// Create expected schemaType proto.
@@ -586,7 +798,7 @@
.build();
List<SchemaTypeConfigProto> expectedTypes = new ArrayList<>();
- expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(existingSchemas);
expectedTypes.addAll(expectedProto.getTypesList());
assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
.containsExactlyElementsIn(expectedTypes);
@@ -594,20 +806,30 @@
@Test
public void testSetSchema_existingSchemaRetainsVisibilitySetting() throws Exception {
+ PackageIdentifier package1 =
+ new PackageIdentifier("package1", /*sha256Certificate=*/ new byte[] {100});
+
String prefix = AppSearchImpl.createPrefix("package", "database");
mAppSearchImpl.setSchema(
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
+ /*schemasPackageAccessible=*/ ImmutableMap.of(
+ "schema1", ImmutableList.of(package1)),
/*forceOverride=*/ false);
- // "schema1" is platform hidden now
+ // "schema1" is platform hidden now and package visible to package1
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
.isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
.isFalse();
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaPackageAccessible(prefix, prefix + "schema1", package1))
+ .isTrue();
// Add a new schema, and include the already-existing "schema1"
mAppSearchImpl.setSchema(
@@ -617,10 +839,11 @@
new AppSearchSchema.Builder("schema1").build(),
new AppSearchSchema.Builder("schema2").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
+ /*schemasPackageAccessible=*/ ImmutableMap.of(
+ "schema1", ImmutableList.of(package1)),
/*forceOverride=*/ false);
- // Check that "schema1" is still platform hidden, but "schema2" is the default platform
- // visible.
+ // Check that "schema1" still has the same visibility settings
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
@@ -629,12 +852,27 @@
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
+ .isSchemaPackageAccessible(prefix, prefix + "schema1", package1))
+ .isTrue();
+
+ // "schema2" has default visibility settings
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
.isSchemaPlatformSurfaceable(prefix, prefix + "schema2"))
.isTrue();
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaPackageAccessible(prefix, prefix + "schema2", package1))
+ .isFalse();
}
@Test
public void testRemoveSchema() throws Exception {
+ List<SchemaTypeConfigProto> existingSchemas =
+ mAppSearchImpl.getSchemaProtoLocked().getTypesList();
+
List<AppSearchSchema> schemas =
ImmutableList.of(
new AppSearchSchema.Builder("Email").build(),
@@ -645,6 +883,7 @@
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
// Create expected schemaType proto.
@@ -660,7 +899,7 @@
// Check both schema Email and Document saved correctly.
List<SchemaTypeConfigProto> expectedTypes = new ArrayList<>();
- expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(existingSchemas);
expectedTypes.addAll(expectedProto.getTypesList());
assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
.containsExactlyElementsIn(expectedTypes);
@@ -677,6 +916,7 @@
"database1",
finalSchemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false));
assertThat(e).hasMessageThat().contains("Schema is incompatible");
assertThat(e).hasMessageThat().contains("Deleted types: [package$database1/Document]");
@@ -687,6 +927,7 @@
"database1",
finalSchemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ true);
// Check Document schema is removed.
@@ -698,7 +939,7 @@
.build();
expectedTypes = new ArrayList<>();
- expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(existingSchemas);
expectedTypes.addAll(expectedProto.getTypesList());
assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
.containsExactlyElementsIn(expectedTypes);
@@ -706,6 +947,9 @@
@Test
public void testRemoveSchema_differentDataBase() throws Exception {
+ List<SchemaTypeConfigProto> existingSchemas =
+ mAppSearchImpl.getSchemaProtoLocked().getTypesList();
+
// Create schemas
List<AppSearchSchema> schemas =
ImmutableList.of(
@@ -718,12 +962,14 @@
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
mAppSearchImpl.setSchema(
"package",
"database2",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
// Create expected schemaType proto.
@@ -745,7 +991,7 @@
// Check Email and Document is saved in database 1 and 2 correctly.
List<SchemaTypeConfigProto> expectedTypes = new ArrayList<>();
- expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(existingSchemas);
expectedTypes.addAll(expectedProto.getTypesList());
assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
.containsExactlyElementsIn(expectedTypes);
@@ -757,6 +1003,7 @@
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ true);
// Create expected schemaType list, database 1 should only contain Email but database 2
@@ -776,7 +1023,7 @@
// Check nothing changed in database2.
expectedTypes = new ArrayList<>();
- expectedTypes.add(mVisibilitySchemaProto);
+ expectedTypes.addAll(existingSchemas);
expectedTypes.addAll(expectedProto.getTypesList());
assertThat(mAppSearchImpl.getSchemaProtoLocked().getTypesList())
.containsExactlyElementsIn(expectedTypes);
@@ -784,49 +1031,71 @@
@Test
public void testRemoveSchema_removedFromVisibilityStore() throws Exception {
+ PackageIdentifier package1 =
+ new PackageIdentifier("package1", /*sha256Certificate=*/ new byte[] {100});
+
String prefix = AppSearchImpl.createPrefix("package", "database");
mAppSearchImpl.setSchema(
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
+ /*schemasPackageAccessible=*/ ImmutableMap.of(
+ "schema1", ImmutableList.of(package1)),
/*forceOverride=*/ false);
- // "schema1" is platform hidden now
+ // "schema1" is platform hidden now and package accessible
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
.isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
.isFalse();
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaPackageAccessible(prefix, prefix + "schema1", package1))
+ .isTrue();
// Remove "schema1" by force overriding
mAppSearchImpl.setSchema(
"package",
"database",
- Collections.emptyList(),
+ /*schemas=*/ Collections.emptyList(),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ true);
- // Check that "schema1" is no longer considered platform hidden
+ // Check that "schema1" is no longer considered platform hidden or package accessible
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
.isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
.isTrue();
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaPackageAccessible(prefix, prefix + "schema1", package1))
+ .isFalse();
// Add "schema1" back, it gets default visibility settings which means it's not platform
- // hidden.
+ // hidden and not package accessible
mAppSearchImpl.setSchema(
"package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
.isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
.isTrue();
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaPackageAccessible(prefix, prefix + "schema1", package1))
+ .isFalse();
}
@Test
@@ -837,6 +1106,7 @@
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
assertThat(
mAppSearchImpl
@@ -853,6 +1123,7 @@
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
assertThat(
mAppSearchImpl
@@ -862,6 +1133,46 @@
}
@Test
+ public void testSetSchema_defaultNotPackageAccessible() throws Exception {
+ PackageIdentifier package1 =
+ new PackageIdentifier("package1", /*sha256Certificate=*/ new byte[] {100});
+
+ String prefix = AppSearchImpl.createPrefix("package", "database");
+ mAppSearchImpl.setSchema(
+ "package",
+ "database",
+ Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaPackageAccessible(prefix, prefix + "Schema", package1))
+ .isFalse();
+ }
+
+ @Test
+ public void testSetSchema_packageAccessible() throws Exception {
+ PackageIdentifier package1 =
+ new PackageIdentifier("package1", /*sha256Certificate=*/ new byte[] {100});
+
+ String prefix = AppSearchImpl.createPrefix("package", "database");
+ mAppSearchImpl.setSchema(
+ "package",
+ "database",
+ Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ ImmutableMap.of("Schema", ImmutableList.of(package1)),
+ /*forceOverride=*/ false);
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaPackageAccessible(prefix, prefix + "Schema", package1))
+ .isTrue();
+ }
+
+ @Test
public void testHasSchemaType() throws Exception {
// Nothing exists yet
assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isFalse();
@@ -871,6 +1182,7 @@
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isTrue();
@@ -892,6 +1204,7 @@
"database1",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
assertThat(mAppSearchImpl.getPrefixesLocked())
.containsExactly(
@@ -905,6 +1218,7 @@
"database2",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
assertThat(mAppSearchImpl.getPrefixesLocked())
.containsExactly(
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
index 415c1f5..e491ac3 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
@@ -18,6 +18,10 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.appsearch.PackageIdentifier;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
@@ -70,11 +74,12 @@
}
@Test
- public void testSetVisibility() throws Exception {
+ public void testSetVisibility_platformSurfaceable() throws Exception {
mVisibilityStore.setVisibility(
"prefix",
/*schemasNotPlatformSurfaceable=*/ ImmutableSet.of(
- "prefix/schema1", "prefix/schema2"));
+ "prefix/schema1", "prefix/schema2"),
+ /*schemasPackageAccessible=*/ Collections.emptyMap());
assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
.isFalse();
assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
@@ -85,7 +90,8 @@
mVisibilityStore.setVisibility(
"prefix",
/*schemasNotPlatformSurfaceable=*/ ImmutableSet.of(
- "prefix/schema1", "prefix/schema3"));
+ "prefix/schema1", "prefix/schema3"),
+ /*schemasPackageAccessible=*/ Collections.emptyMap());
assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
.isFalse();
assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
@@ -94,7 +100,9 @@
.isFalse();
mVisibilityStore.setVisibility(
- "prefix", /*schemasNotPlatformSurfaceable=*/ Collections.emptySet());
+ "prefix",
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap());
assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
.isTrue();
assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
@@ -104,13 +112,72 @@
}
@Test
+ public void testSetVisibility_packageAccessible() throws Exception {
+ PackageIdentifier package1 =
+ new PackageIdentifier("package1", /*sha256Certificate=*/ new byte[] {100});
+ PackageIdentifier package2 =
+ new PackageIdentifier("package2", /*sha256Certificate=*/ new byte[] {100});
+ PackageIdentifier package3 =
+ new PackageIdentifier("package3", /*sha256Certificate=*/ new byte[] {100});
+
+ mVisibilityStore.setVisibility(
+ "prefix",
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
+ /*schemasPackageAccessible=*/ ImmutableMap.of(
+ "prefix/schema1", ImmutableList.of(package1),
+ "prefix/schema2", ImmutableList.of(package2)));
+ assertThat(mVisibilityStore.isSchemaPackageAccessible("prefix", "prefix/schema1", package1))
+ .isTrue();
+ assertThat(mVisibilityStore.isSchemaPackageAccessible("prefix", "prefix/schema2", package2))
+ .isTrue();
+
+ // New .setVisibility() call completely overrides previous visibility settings. So
+ // "schema2" isn't preserved.
+ mVisibilityStore.setVisibility(
+ "prefix",
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
+ /*schemasPackageAccessible=*/ ImmutableMap.of(
+ "prefix/schema1", ImmutableList.of(package1),
+ "prefix/schema3", ImmutableList.of(package3)));
+ assertThat(mVisibilityStore.isSchemaPackageAccessible("prefix", "prefix/schema1", package1))
+ .isTrue();
+ assertThat(mVisibilityStore.isSchemaPackageAccessible("prefix", "prefix/schema2", package2))
+ .isFalse();
+ assertThat(mVisibilityStore.isSchemaPackageAccessible("prefix", "prefix/schema3", package3))
+ .isTrue();
+
+ mVisibilityStore.setVisibility(
+ "prefix",
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptySet(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap());
+ assertThat(mVisibilityStore.isSchemaPackageAccessible("prefix", "prefix/schema1", package1))
+ .isFalse();
+ assertThat(mVisibilityStore.isSchemaPackageAccessible("prefix", "prefix/schema2", package2))
+ .isFalse();
+ assertThat(mVisibilityStore.isSchemaPackageAccessible("prefix", "prefix/schema3", package3))
+ .isFalse();
+ }
+
+ @Test
public void testEmptyPrefix() throws Exception {
+ PackageIdentifier package1 =
+ new PackageIdentifier("package1", /*sha256Certificate=*/ new byte[] {100});
+ PackageIdentifier package2 =
+ new PackageIdentifier("package2", /*sha256Certificate=*/ new byte[] {100});
+
mVisibilityStore.setVisibility(
/*prefix=*/ "",
- /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of("schema1", "schema2"));
+ /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of("schema1", "schema2"),
+ /*schemasPackageAccessible=*/ ImmutableMap.of(
+ "schema1", ImmutableList.of(package1),
+ "schema2", ImmutableList.of(package2)));
assertThat(mVisibilityStore.isSchemaPlatformSurfaceable(/*prefix=*/ "", "schema1"))
.isFalse();
assertThat(mVisibilityStore.isSchemaPlatformSurfaceable(/*prefix=*/ "", "schema2"))
.isFalse();
+ assertThat(mVisibilityStore.isSchemaPackageAccessible(/*prefix=*/ "", "schema1", package1))
+ .isTrue();
+ assertThat(mVisibilityStore.isSchemaPackageAccessible(/*prefix=*/ "", "schema2", package2))
+ .isTrue();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java
index 340a1d9..bb2b1c2 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/InvalidationTrackerTest.java
@@ -22,7 +22,9 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.IBiometricAuthenticator;
@@ -44,21 +46,25 @@
@Test
public void testCallbackReceived_whenAllStrongSensorsInvalidated() throws Exception {
final IBiometricAuthenticator authenticator1 = mock(IBiometricAuthenticator.class);
+ when(authenticator1.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
final TestSensor sensor1 = new TestSensor(0 /* id */,
BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
authenticator1);
final IBiometricAuthenticator authenticator2 = mock(IBiometricAuthenticator.class);
+ when(authenticator2.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
final TestSensor sensor2 = new TestSensor(1 /* id */,
BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
authenticator2);
final IBiometricAuthenticator authenticator3 = mock(IBiometricAuthenticator.class);
+ when(authenticator3.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
final TestSensor sensor3 = new TestSensor(2 /* id */,
BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG,
authenticator3);
final IBiometricAuthenticator authenticator4 = mock(IBiometricAuthenticator.class);
+ when(authenticator4.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
final TestSensor sensor4 = new TestSensor(3 /* id */,
BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_WEAK,
authenticator4);
@@ -71,7 +77,8 @@
final IInvalidationCallback callback = mock(IInvalidationCallback.class);
final InvalidationTracker tracker =
- InvalidationTracker.start(sensors, 0 /* userId */, 0 /* fromSensorId */, callback);
+ InvalidationTracker.start(mock(Context.class), sensors, 0 /* userId */,
+ 0 /* fromSensorId */, callback);
// The sensor which the request originated from should not be requested to invalidate
// its authenticatorId.
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 24e7d7d..cc4541b 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -71,10 +71,12 @@
@Test
public void testClientDuplicateFinish_ignoredBySchedulerAndDoesNotCrash() {
- final ClientMonitor.LazyDaemon<Object> nonNullDaemon = () -> mock(Object.class);
+ final HalClientMonitor.LazyDaemon<Object> nonNullDaemon = () -> mock(Object.class);
- final ClientMonitor<Object> client1 = new TestClientMonitor(mContext, mToken, nonNullDaemon);
- final ClientMonitor<Object> client2 = new TestClientMonitor(mContext, mToken, nonNullDaemon);
+ final HalClientMonitor<Object> client1 =
+ new TestClientMonitor(mContext, mToken, nonNullDaemon);
+ final HalClientMonitor<Object> client2 =
+ new TestClientMonitor(mContext, mToken, nonNullDaemon);
mScheduler.scheduleClientMonitor(client1);
mScheduler.scheduleClientMonitor(client2);
@@ -87,19 +89,19 @@
// Even if second client has a non-null daemon, it needs to be canceled.
Object daemon2 = mock(Object.class);
- final ClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null;
- final ClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2;
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null;
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2;
final TestClientMonitor client1 = new TestClientMonitor(mContext, mToken, lazyDaemon1);
final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2);
- final ClientMonitor.Callback callback1 = mock(ClientMonitor.Callback.class);
- final ClientMonitor.Callback callback2 = mock(ClientMonitor.Callback.class);
+ final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
+ final BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class);
// Pretend the scheduler is busy so the first operation doesn't start right away. We want
// to pretend like there are two operations in the queue before kicking things off
mScheduler.mCurrentOperation = new BiometricScheduler.Operation(
- mock(ClientMonitor.class), mock(ClientMonitor.Callback.class));
+ mock(BaseClientMonitor.class), mock(BaseClientMonitor.Callback.class));
mScheduler.scheduleClientMonitor(client1, callback1);
assertEquals(1, mScheduler.mPendingOperations.size());
@@ -124,8 +126,8 @@
// Second non-BiometricPrompt client has a valid daemon
final Object daemon2 = mock(Object.class);
- final ClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null;
- final ClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2;
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null;
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2;
final ClientMonitorCallbackConverter listener1 = mock(ClientMonitorCallbackConverter.class);
@@ -133,13 +135,13 @@
new BiometricPromptClientMonitor(mContext, mToken, lazyDaemon1, listener1);
final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2);
- final ClientMonitor.Callback callback1 = mock(ClientMonitor.Callback.class);
- final ClientMonitor.Callback callback2 = mock(ClientMonitor.Callback.class);
+ final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
+ final BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class);
// Pretend the scheduler is busy so the first operation doesn't start right away. We want
// to pretend like there are two operations in the queue before kicking things off
mScheduler.mCurrentOperation = new BiometricScheduler.Operation(
- mock(ClientMonitor.class), mock(ClientMonitor.Callback.class));
+ mock(BaseClientMonitor.class), mock(BaseClientMonitor.Callback.class));
mScheduler.scheduleClientMonitor(client1, callback1);
assertEquals(1, mScheduler.mPendingOperations.size());
@@ -165,16 +167,16 @@
@Test
public void testCancelNotInvoked_whenOperationWaitingForCookie() {
- final ClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> mock(Object.class);
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> mock(Object.class);
final BiometricPromptClientMonitor client1 = new BiometricPromptClientMonitor(mContext,
mToken, lazyDaemon1, mock(ClientMonitorCallbackConverter.class));
- final ClientMonitor.Callback callback1 = mock(ClientMonitor.Callback.class);
+ final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
// Schedule a BiometricPrompt authentication request
mScheduler.scheduleClientMonitor(client1, callback1);
- assertEquals(Operation.STATE_WAITING_FOR_COOKIE, mScheduler.mCurrentOperation.state);
- assertEquals(client1, mScheduler.mCurrentOperation.clientMonitor);
+ assertEquals(Operation.STATE_WAITING_FOR_COOKIE, mScheduler.mCurrentOperation.mState);
+ assertEquals(client1, mScheduler.mCurrentOperation.mClientMonitor);
assertEquals(0, mScheduler.mPendingOperations.size());
// Request it to be canceled. The operation can be canceled immediately, and the scheduler
@@ -205,7 +207,7 @@
}
}
- private static class TestClientMonitor extends ClientMonitor<Object> {
+ private static class TestClientMonitor extends HalClientMonitor<Object> {
private boolean mUnableToStart;
private boolean mStarted;
@@ -221,7 +223,6 @@
0 /* statsAction */, 0 /* statsClient */);
}
-
@Override
public void unableToStart() {
assertFalse(mUnableToStart);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
index efdbda3..04a7122 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceProviderTest.java
@@ -31,8 +31,9 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import org.junit.Before;
@@ -94,7 +95,7 @@
final BiometricScheduler scheduler =
mFaceProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
for (int i = 0; i < numFakeOperations; i++) {
- final ClientMonitor testMonitor = mock(ClientMonitor.class);
+ final HalClientMonitor testMonitor = mock(HalClientMonitor.class);
when(testMonitor.getFreshDaemon()).thenReturn(new Object());
scheduler.scheduleClientMonitor(testMonitor);
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
index 99aab5c..392535e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.face.hidl;
+import static junit.framework.Assert.assertEquals;
+
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -76,6 +78,12 @@
}
@Test
+ public void getAuthenticatorId_doesNotCrashWhenIdNotFound() {
+ assertEquals(0, mFace10.getAuthenticatorId(0 /* sensorId */, 111 /* userId */));
+ waitForIdle();
+ }
+
+ @Test
public void scheduleRevokeChallenge_doesNotCrash() {
mFace10.scheduleRevokeChallenge(0 /* sensorId */, 0 /* userId */, mBinder, TAG,
0 /* challenge */);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
index 624775b..d149880 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
@@ -31,8 +31,9 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
-import com.android.server.biometrics.sensors.ClientMonitor;
+import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
@@ -97,7 +98,7 @@
final BiometricScheduler scheduler =
mFingerprintProvider.mSensors.get(prop.commonProps.sensorId).getScheduler();
for (int i = 0; i < numFakeOperations; i++) {
- final ClientMonitor testMonitor = mock(ClientMonitor.class);
+ final HalClientMonitor testMonitor = mock(HalClientMonitor.class);
when(testMonitor.getFreshDaemon()).thenReturn(new Object());
scheduler.scheduleClientMonitor(testMonitor);
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
index b2aeb33..61cc8e6 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
@@ -16,6 +16,8 @@
package com.android.server.biometrics.sensors.fingerprint.hidl;
+import static junit.framework.Assert.assertEquals;
+
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -85,6 +87,12 @@
}
@Test
+ public void getAuthenticatorId_doesNotCrashWhenIdNotFound() {
+ assertEquals(0, mFingerprint21.getAuthenticatorId(0 /* sensorId */, 111 /* userId */));
+ waitForIdle();
+ }
+
+ @Test
public void halServiceDied_resetsScheduler() {
// It's difficult to test the linkToDeath --> serviceDied path, so let's just invoke
// serviceDied directly.
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
new file mode 100644
index 0000000..0cf0af3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.graphics.fonts;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.content.Context;
+import android.os.FileUtils;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class UpdatableFontDirTest {
+
+ /**
+ * A {@link UpdatableFontDir.FontFileParser} for testing. Instead of using real font files,
+ * this test uses fake font files. A fake font file has its version as its file content.
+ */
+ private static class FakeFontFileParser implements UpdatableFontDir.FontFileParser {
+ @Override
+ public long getVersion(File file) throws IOException {
+ return Long.parseLong(FileUtils.readTextFile(file, 100, ""));
+ }
+ }
+
+ private File mCacheDir;
+ private File mUpdatableFontFilesDir;
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mCacheDir = new File(context.getCacheDir(), "UpdatableFontDirTest");
+ FileUtils.deleteContentsAndDir(mCacheDir);
+ mCacheDir.mkdirs();
+ mUpdatableFontFilesDir = new File(mCacheDir, "updatable_fonts");
+ mUpdatableFontFilesDir.mkdir();
+ }
+
+ @After
+ public void tearDown() {
+ FileUtils.deleteContentsAndDir(mCacheDir);
+ }
+
+ @Test
+ public void construct() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dirForPreparation = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+ installFontFile(dirForPreparation, "foo.ttf", "1");
+ installFontFile(dirForPreparation, "bar.ttf", "2");
+ installFontFile(dirForPreparation, "foo.ttf", "3");
+ installFontFile(dirForPreparation, "bar.ttf", "4");
+ // Four font dirs are created.
+ assertThat(mUpdatableFontFilesDir.list()).hasLength(4);
+
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+ assertThat(dir.getFontFileMap()).containsKey("foo.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("foo.ttf"))).isEqualTo(3);
+ assertThat(dir.getFontFileMap()).containsKey("bar.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("bar.ttf"))).isEqualTo(4);
+ // Outdated font dir should be deleted.
+ assertThat(mUpdatableFontFilesDir.list()).hasLength(2);
+ }
+
+ @Test
+ public void construct_empty() {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+ assertThat(dir.getFontFileMap()).isEmpty();
+ }
+
+ @Test
+ public void installFontFile() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+
+ installFontFile(dir, "test.ttf", "1");
+ assertThat(dir.getFontFileMap()).containsKey("test.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("test.ttf"))).isEqualTo(1);
+ }
+
+ @Test
+ public void installFontFile_upgrade() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+
+ installFontFile(dir, "test.ttf", "1");
+ Map<String, File> mapBeforeUpgrade = dir.getFontFileMap();
+ installFontFile(dir, "test.ttf", "2");
+ assertThat(dir.getFontFileMap()).containsKey("test.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("test.ttf"))).isEqualTo(2);
+ assertThat(mapBeforeUpgrade).containsKey("test.ttf");
+ assertWithMessage("Older fonts should not be deleted until next loadFontFileMap")
+ .that(parser.getVersion(mapBeforeUpgrade.get("test.ttf"))).isEqualTo(1);
+ }
+
+ @Test
+ public void installFontFile_downgrade() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+
+ installFontFile(dir, "test.ttf", "2");
+ installFontFile(dir, "test.ttf", "1");
+ assertThat(dir.getFontFileMap()).containsKey("test.ttf");
+ assertWithMessage("Font should not be downgraded to an older version")
+ .that(parser.getVersion(dir.getFontFileMap().get("test.ttf"))).isEqualTo(2);
+ }
+
+ @Test
+ public void installFontFile_multiple() throws Exception {
+ FakeFontFileParser parser = new FakeFontFileParser();
+ UpdatableFontDir dir = new UpdatableFontDir(mUpdatableFontFilesDir, parser);
+
+ installFontFile(dir, "foo.ttf", "1");
+ installFontFile(dir, "bar.ttf", "2");
+ assertThat(dir.getFontFileMap()).containsKey("foo.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("foo.ttf"))).isEqualTo(1);
+ assertThat(dir.getFontFileMap()).containsKey("bar.ttf");
+ assertThat(parser.getVersion(dir.getFontFileMap().get("bar.ttf"))).isEqualTo(2);
+ }
+
+ private void installFontFile(UpdatableFontDir dir, String name, String content)
+ throws IOException {
+ File file = File.createTempFile(name, "", mCacheDir);
+ FileUtils.stringToFile(file, content);
+ try (FileInputStream in = new FileInputStream(file)) {
+ dir.installFontFile(name, in.getFD());
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
index e5bcedb..aeeca1a 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
@@ -59,6 +59,15 @@
+ " </allowed-values>"
+ " <default-value string-value=\"none\" />"
+ " </setting>"
+ + " <setting name=\"hdmi_cec_enabled\""
+ + " value-type=\"int\""
+ + " user-configurable=\"true\">"
+ + " <allowed-values>"
+ + " <value int-value=\"0\" />"
+ + " <value int-value=\"1\" />"
+ + " </allowed-values>"
+ + " <default-value int-value=\"1\" />"
+ + " </setting>"
+ " <setting name=\"hdmi_cec_version\""
+ " value-type=\"int\""
+ " user-configurable=\"true\">"
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java
index af119c8..45409c8 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecAtomLoggingTest.java
@@ -15,12 +15,16 @@
*/
package com.android.server.hdmi;
+import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.Constants.PATH_RELATIONSHIP_ANCESTOR;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+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.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -29,8 +33,10 @@
import android.content.Context;
import android.content.ContextWrapper;
+import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.os.Binder;
import android.os.Handler;
import android.os.IPowerManager;
import android.os.IThermalService;
@@ -70,6 +76,7 @@
private FakeNativeWrapper mNativeWrapper;
private HdmiCecNetwork mHdmiCecNetwork;
private Looper mLooper;
+ private Context mContextSpy;
private TestLooper mTestLooper = new TestLooper();
private int mPhysicalAddress = 0x1110;
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
@@ -86,7 +93,7 @@
mLooper = mTestLooper.getLooper();
- Context mContextSpy = spy(new ContextWrapper(
+ mContextSpy = spy(new ContextWrapper(
InstrumentationRegistry.getInstrumentation().getTargetContext()));
PowerManager powerManager = new PowerManager(
@@ -155,9 +162,10 @@
mHdmiCecController.sendCommand(message);
verify(mHdmiCecAtomWriterSpy, times(1)).messageReported(
- message,
- HdmiStatsEnums.OUTGOING,
- SendMessageResult.SUCCESS);
+ eq(message),
+ eq(HdmiStatsEnums.OUTGOING),
+ anyInt(),
+ eq(SendMessageResult.SUCCESS));
}
@Test
@@ -168,7 +176,32 @@
mTestLooper.dispatchAll();
verify(mHdmiCecAtomWriterSpy, times(1)).messageReported(
- message,
- HdmiStatsEnums.INCOMING);
+ eq(message),
+ eq(HdmiStatsEnums.INCOMING),
+ anyInt());
+ }
+
+ @Test
+ public void testMessageReported_calledWithUid() {
+ int callerUid = 1234;
+ int runnerUid = 5678;
+
+ mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON);
+ mHdmiControlServiceSpy.onBootPhase(PHASE_BOOT_COMPLETED);
+
+ Binder.setCallingWorkSourceUid(callerUid);
+
+ mHdmiControlServiceSpy.runOnServiceThread(
+ () -> mHdmiControlServiceSpy.setStandbyMode(true));
+
+ Binder.setCallingWorkSourceUid(runnerUid);
+
+ mTestLooper.dispatchAll();
+
+ verify(mHdmiCecAtomWriterSpy, times(1)).messageReported(
+ any(),
+ anyInt(),
+ eq(callerUid),
+ anyInt());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
index 2f2e97c..b3ee18d 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
@@ -36,6 +36,7 @@
import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.os.Binder;
import android.os.Looper;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
@@ -45,11 +46,15 @@
import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
+import junit.framework.TestCase;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.Optional;
+
/** Tests for {@link com.android.server.hdmi.HdmiCecController} class. */
@SmallTest
@Presubmit
@@ -274,4 +279,33 @@
assertFalse(HdmiCecController.isLanguage("e"));
assertFalse(HdmiCecController.isLanguage("一")); // language code must be ASCII
}
+
+ @Test
+ public void runOnServiceThread_preservesAndRestoresWorkSourceUid() {
+ Binder.setCallingWorkSourceUid(1234);
+ WorkSourceUidReadingRunnable uidReadingRunnable = new WorkSourceUidReadingRunnable();
+ mHdmiCecController.runOnServiceThread(uidReadingRunnable);
+
+ Binder.setCallingWorkSourceUid(5678);
+ mTestLooper.dispatchAll();
+
+ TestCase.assertEquals(Optional.of(1234), uidReadingRunnable.getWorkSourceUid());
+ TestCase.assertEquals(5678, Binder.getCallingWorkSourceUid());
+ }
+
+ @Test
+ public void runOnIoThread_preservesAndRestoresWorkSourceUid() {
+ int callerUid = 1234;
+ int runnerUid = 5678;
+
+ Binder.setCallingWorkSourceUid(callerUid);
+ WorkSourceUidReadingRunnable uidReadingRunnable = new WorkSourceUidReadingRunnable();
+ mHdmiCecController.runOnIoThread(uidReadingRunnable);
+
+ Binder.setCallingWorkSourceUid(runnerUid);
+ mTestLooper.dispatchAll();
+
+ TestCase.assertEquals(Optional.of(callerUid), uidReadingRunnable.getWorkSourceUid());
+ TestCase.assertEquals(runnerUid, Binder.getCallingWorkSourceUid());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index c2268c5..9152e1e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -25,6 +25,7 @@
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static junit.framework.TestCase.assertEquals;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -34,6 +35,7 @@
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener;
+import android.os.Binder;
import android.os.IPowerManager;
import android.os.IThermalService;
import android.os.Looper;
@@ -55,6 +57,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Optional;
/**
* Tests for {@link HdmiControlService} class.
@@ -556,6 +559,23 @@
assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures);
}
+ @Test
+ public void runOnServiceThread_preservesAndRestoresWorkSourceUid() {
+ int callerUid = 1234;
+ int runnerUid = 5678;
+
+ Binder.setCallingWorkSourceUid(callerUid);
+ WorkSourceUidReadingRunnable uidReadingRunnable = new WorkSourceUidReadingRunnable();
+ mHdmiControlService.runOnServiceThread(uidReadingRunnable);
+
+ Binder.setCallingWorkSourceUid(runnerUid);
+
+ mTestLooper.dispatchAll();
+
+ assertEquals(Optional.of(callerUid), uidReadingRunnable.getWorkSourceUid());
+ assertEquals(runnerUid, Binder.getCallingWorkSourceUid());
+ }
+
private static class VolumeControlFeatureCallback extends
IHdmiCecVolumeControlFeatureListener.Stub {
boolean mCallbackReceived = false;
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/WorkSourceUidPreservingRunnableTest.java b/services/tests/servicestests/src/com/android/server/hdmi/WorkSourceUidPreservingRunnableTest.java
new file mode 100644
index 0000000..30df908
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/WorkSourceUidPreservingRunnableTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import static junit.framework.TestCase.assertEquals;
+
+import android.os.Binder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Optional;
+
+@SmallTest
+@Presubmit
+@RunWith(JUnit4.class)
+public class WorkSourceUidPreservingRunnableTest {
+ @Test
+ public void preservesAndRestoresWorkSourceUid() {
+ int callerUid = 1234;
+ int runnerUid = 5678;
+
+ Binder.setCallingWorkSourceUid(callerUid);
+
+ WorkSourceUidReadingRunnable uidReadingRunnable = new WorkSourceUidReadingRunnable();
+ WorkSourceUidPreservingRunnable uidPreservingRunnable =
+ new WorkSourceUidPreservingRunnable(uidReadingRunnable);
+
+ Binder.setCallingWorkSourceUid(runnerUid);
+
+ uidPreservingRunnable.run();
+
+ assertEquals(Optional.of(callerUid), uidReadingRunnable.getWorkSourceUid());
+ assertEquals(runnerUid, Binder.getCallingWorkSourceUid());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/WorkSourceUidReadingRunnable.java b/services/tests/servicestests/src/com/android/server/hdmi/WorkSourceUidReadingRunnable.java
new file mode 100644
index 0000000..15af752
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/WorkSourceUidReadingRunnable.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.os.Binder;
+
+import java.util.Optional;
+
+/**
+ * Reads and records Binder's work source UID when executed.
+ */
+public class WorkSourceUidReadingRunnable implements Runnable {
+ private Optional<Integer> mWorkSourceUid = Optional.empty();
+
+ @Override
+ public void run() {
+ mWorkSourceUid = Optional.of(Binder.getCallingWorkSourceUid());
+ }
+
+ /**
+ * @return The work source UID read during execution, or Optional.empty() if never executed.
+ */
+ public Optional<Integer> getWorkSourceUid() {
+ return mWorkSourceUid;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
index 99ecb86..a7b32ac 100644
--- a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
@@ -61,7 +61,7 @@
* adb install -r $OUT/data/app/JobTestApp/JobTestApp.apk
* adb install -r $OUT/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
* adb shell am instrument -e class 'com.android.server.job.BackgroundRestrictionsTest' -w \
- com.android.frameworks.servicestests
+ * com.android.frameworks.servicestests
* </pre>
*/
@RunWith(AndroidJUnit4.class)
@@ -70,14 +70,14 @@
private static final String TAG = BackgroundRestrictionsTest.class.getSimpleName();
private static final String TEST_APP_PACKAGE = "com.android.servicestests.apps.jobtestapp";
private static final String TEST_APP_ACTIVITY = TEST_APP_PACKAGE + ".TestJobActivity";
- private static final long POLL_INTERVAL = 2000;
+ private static final long POLL_INTERVAL = 500;
private static final long DEFAULT_WAIT_TIMEOUT = 5000;
private Context mContext;
private AppOpsManager mAppOpsManager;
private IDeviceIdleController mDeviceIdleController;
private IActivityManager mIActivityManager;
- private int mTestJobId;
+ private volatile int mTestJobId = -1;
private int mTestPackageUid;
/* accesses must be synchronized on itself */
private final TestJobStatus mTestJobStatus = new TestJobStatus();
@@ -111,40 +111,55 @@
ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
mIActivityManager = ActivityManager.getService();
mTestPackageUid = mContext.getPackageManager().getPackageUid(TEST_APP_PACKAGE, 0);
- mTestJobId = (int) (SystemClock.uptimeMillis() / 1000);
mTestJobStatus.reset();
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_JOB_STARTED);
intentFilter.addAction(ACTION_JOB_STOPPED);
mContext.registerReceiver(mJobStateChangeReceiver, intentFilter);
setAppOpsModeAllowed(true);
- setPowerWhiteListed(false);
+ setPowerExemption(false);
}
- private void scheduleAndAssertJobStarted() throws Exception {
+ private void scheduleTestJob() {
+ mTestJobId = (int) (SystemClock.uptimeMillis() / 1000);
final Intent scheduleJobIntent = new Intent(TestJobActivity.ACTION_START_JOB);
scheduleJobIntent.putExtra(TestJobActivity.EXTRA_JOB_ID_KEY, mTestJobId);
scheduleJobIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
scheduleJobIntent.setComponent(new ComponentName(TEST_APP_PACKAGE, TEST_APP_ACTIVITY));
mContext.startActivity(scheduleJobIntent);
+ }
+
+ private void scheduleAndAssertJobStarted() throws Exception {
+ scheduleTestJob();
Thread.sleep(TestJobActivity.JOB_MINIMUM_LATENCY);
assertTrue("Job did not start after scheduling", awaitJobStart(DEFAULT_WAIT_TIMEOUT));
}
- @Test
@FlakyTest
- public void testPowerWhiteList() throws Exception {
+ @Test
+ public void testPowerExemption() throws Exception {
scheduleAndAssertJobStarted();
setAppOpsModeAllowed(false);
mIActivityManager.makePackageIdle(TEST_APP_PACKAGE, UserHandle.USER_CURRENT);
- assertTrue("Job did not stop after making idle", awaitJobStop(DEFAULT_WAIT_TIMEOUT));
- setPowerWhiteListed(true);
- Thread.sleep(TestJobActivity.JOB_INITIAL_BACKOFF);
- assertTrue("Job did not start after adding to power whitelist",
- awaitJobStart(DEFAULT_WAIT_TIMEOUT));
- setPowerWhiteListed(false);
- assertTrue("Job did not stop after removing from power whitelist",
+ assertTrue("Job did not stop after putting app under bg-restriction",
awaitJobStop(DEFAULT_WAIT_TIMEOUT));
+
+ setPowerExemption(true);
+ scheduleTestJob();
+ Thread.sleep(TestJobActivity.JOB_MINIMUM_LATENCY);
+ assertTrue("Job did not start when the app was in the power exemption list",
+ awaitJobStart(DEFAULT_WAIT_TIMEOUT));
+
+ setPowerExemption(false);
+ assertTrue("Job did not stop after removing from the power exemption list",
+ awaitJobStop(DEFAULT_WAIT_TIMEOUT));
+
+ scheduleTestJob();
+ Thread.sleep(TestJobActivity.JOB_MINIMUM_LATENCY);
+ assertFalse("Job started under bg-restrictions", awaitJobStart(DEFAULT_WAIT_TIMEOUT));
+ setPowerExemption(true);
+ assertTrue("Job did not start when the app was in the power exemption list",
+ awaitJobStart(DEFAULT_WAIT_TIMEOUT));
}
@Test
@@ -167,13 +182,13 @@
mContext.unregisterReceiver(mJobStateChangeReceiver);
Thread.sleep(500); // To avoid race with register in the next setUp
setAppOpsModeAllowed(true);
- setPowerWhiteListed(false);
+ setPowerExemption(false);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.FORCED_APP_STANDBY_ENABLED, 1);
}
- private void setPowerWhiteListed(boolean whitelist) throws RemoteException {
- if (whitelist) {
+ private void setPowerExemption(boolean exempt) throws RemoteException {
+ if (exempt) {
mDeviceIdleController.addPowerSaveWhitelistApp(TEST_APP_PACKAGE);
} else {
mDeviceIdleController.removePowerSaveWhitelistApp(TEST_APP_PACKAGE);
@@ -214,6 +229,7 @@
int jobId;
int stopReason;
boolean running;
+
private void reset() {
running = false;
stopReason = jobId = 0;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java
index 46f43e7..32445fd 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowDataTest.java
@@ -19,22 +19,44 @@
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
+
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.security.GeneralSecurityException;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
/**
* atest FrameworksServicesTests:RebootEscrowDataTest
*/
@RunWith(AndroidJUnit4.class)
public class RebootEscrowDataTest {
private RebootEscrowKey mKey;
+ private SecretKey mKeyStoreEncryptionKey;
+
+ private SecretKey generateNewRebootEscrowEncryptionKey() throws GeneralSecurityException {
+ KeyGenerator generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
+ generator.init(new KeyGenParameterSpec.Builder(
+ "reboot_escrow_data_test_key",
+ KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setKeySize(256)
+ .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .build());
+ return generator.generateKey();
+ }
@Before
public void generateKey() throws Exception {
mKey = RebootEscrowKey.generate();
+ mKeyStoreEncryptionKey = generateNewRebootEscrowEncryptionKey();
}
private static byte[] getTestSp() {
@@ -47,36 +69,49 @@
@Test(expected = NullPointerException.class)
public void fromEntries_failsOnNull() throws Exception {
- RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, null);
+ RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, null, mKeyStoreEncryptionKey);
}
@Test(expected = NullPointerException.class)
public void fromEncryptedData_failsOnNullData() throws Exception {
byte[] testSp = getTestSp();
- RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp);
+ RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp,
+ mKeyStoreEncryptionKey);
RebootEscrowKey key = RebootEscrowKey.fromKeyBytes(expected.getKey().getKeyBytes());
- RebootEscrowData.fromEncryptedData(key, null);
+ RebootEscrowData.fromEncryptedData(key, null, mKeyStoreEncryptionKey);
}
@Test(expected = NullPointerException.class)
public void fromEncryptedData_failsOnNullKey() throws Exception {
byte[] testSp = getTestSp();
- RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp);
- RebootEscrowData.fromEncryptedData(null, expected.getBlob());
+ RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp,
+ mKeyStoreEncryptionKey);
+ RebootEscrowData.fromEncryptedData(null, expected.getBlob(), mKeyStoreEncryptionKey);
}
@Test
public void fromEntries_loopback_success() throws Exception {
byte[] testSp = getTestSp();
- RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp);
+ RebootEscrowData expected = RebootEscrowData.fromSyntheticPassword(mKey, (byte) 2, testSp,
+ mKeyStoreEncryptionKey);
RebootEscrowKey key = RebootEscrowKey.fromKeyBytes(expected.getKey().getKeyBytes());
- RebootEscrowData actual = RebootEscrowData.fromEncryptedData(key, expected.getBlob());
+ RebootEscrowData actual = RebootEscrowData.fromEncryptedData(key, expected.getBlob(),
+ mKeyStoreEncryptionKey);
assertThat(actual.getSpVersion(), is(expected.getSpVersion()));
- assertThat(actual.getIv(), is(expected.getIv()));
assertThat(actual.getKey().getKeyBytes(), is(expected.getKey().getKeyBytes()));
assertThat(actual.getBlob(), is(expected.getBlob()));
assertThat(actual.getSyntheticPassword(), is(expected.getSyntheticPassword()));
}
+
+ @Test
+ public void aesEncryptedBlob_loopback_success() throws Exception {
+ byte[] testSp = getTestSp();
+ byte [] encrypted = AesEncryptionUtil.encrypt(mKeyStoreEncryptionKey, testSp);
+ byte [] decrypted = AesEncryptionUtil.decrypt(mKeyStoreEncryptionKey, encrypted);
+
+ assertThat(decrypted, is(testSp));
+ }
+
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
index 98d6452..f74e45b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
@@ -61,6 +61,9 @@
import java.io.File;
import java.util.ArrayList;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
@@ -77,15 +80,25 @@
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
};
+ // Hex encoding of a randomly generated AES key for test.
+ private static final byte[] TEST_AES_KEY = new byte[] {
+ 0x48, 0x19, 0x12, 0x54, 0x13, 0x13, 0x52, 0x31,
+ 0x44, 0x74, 0x61, 0x54, 0x29, 0x74, 0x37, 0x61,
+ 0x70, 0x70, 0x75, 0x25, 0x27, 0x31, 0x49, 0x09,
+ 0x26, 0x52, 0x72, 0x63, 0x63, 0x61, 0x78, 0x23,
+ };
+
private Context mContext;
private UserManager mUserManager;
private RebootEscrowManager.Callbacks mCallbacks;
private IRebootEscrow mRebootEscrow;
+ private RebootEscrowKeyStoreManager mKeyStoreManager;
LockSettingsStorageTestable mStorage;
private MockableRebootEscrowInjected mInjected;
private RebootEscrowManager mService;
+ private SecretKey mAesKey;
public interface MockableRebootEscrowInjected {
int getBootCount();
@@ -98,9 +111,11 @@
private final RebootEscrowProviderInterface mRebootEscrowProvider;
private final UserManager mUserManager;
private final MockableRebootEscrowInjected mInjected;
+ private final RebootEscrowKeyStoreManager mKeyStoreManager;
MockInjector(Context context, UserManager userManager,
IRebootEscrow rebootEscrow,
+ RebootEscrowKeyStoreManager keyStoreManager,
MockableRebootEscrowInjected injected) {
super(context);
mRebootEscrow = rebootEscrow;
@@ -114,6 +129,7 @@
};
mRebootEscrowProvider = new RebootEscrowProviderHalImpl(halInjector);
mUserManager = userManager;
+ mKeyStoreManager = keyStoreManager;
mInjected = injected;
}
@@ -128,6 +144,11 @@
}
@Override
+ public RebootEscrowKeyStoreManager getKeyStoreManager() {
+ return mKeyStoreManager;
+ }
+
+ @Override
public int getBootCount() {
return mInjected.getBootCount();
}
@@ -144,6 +165,11 @@
mUserManager = mock(UserManager.class);
mCallbacks = mock(RebootEscrowManager.Callbacks.class);
mRebootEscrow = mock(IRebootEscrow.class);
+ mKeyStoreManager = mock(RebootEscrowKeyStoreManager.class);
+ mAesKey = new SecretKeySpec(TEST_AES_KEY, "AES");
+
+ when(mKeyStoreManager.getKeyStoreEncryptionKey()).thenReturn(mAesKey);
+ when(mKeyStoreManager.generateKeyStoreEncryptionKeyIfNeeded()).thenReturn(mAesKey);
mStorage = new LockSettingsStorageTestable(mContext,
new File(InstrumentationRegistry.getContext().getFilesDir(), "locksettings"));
@@ -160,7 +186,7 @@
when(mCallbacks.isUserSecure(SECURE_SECONDARY_USER_ID)).thenReturn(true);
mInjected = mock(MockableRebootEscrowInjected.class);
mService = new RebootEscrowManager(new MockInjector(mContext, mUserManager, mRebootEscrow,
- mInjected), mCallbacks, mStorage);
+ mKeyStoreManager, mInjected), mCallbacks, mStorage);
}
@Test
@@ -213,6 +239,7 @@
assertNotNull(
mStorage.getString(RebootEscrowManager.REBOOT_ESCROW_ARMED_KEY, null, USER_SYSTEM));
verify(mRebootEscrow).storeKey(any());
+ verify(mKeyStoreManager).getKeyStoreEncryptionKey();
assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID));
assertFalse(mStorage.hasRebootEscrow(NONSECURE_SECONDARY_USER_ID));
@@ -300,6 +327,7 @@
ArgumentCaptor<byte[]> keyByteCaptor = ArgumentCaptor.forClass(byte[].class);
assertTrue(mService.armRebootEscrowIfNeeded());
verify(mRebootEscrow).storeKey(keyByteCaptor.capture());
+ verify(mKeyStoreManager).getKeyStoreEncryptionKey();
assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID));
assertFalse(mStorage.hasRebootEscrow(NONSECURE_SECONDARY_USER_ID));
@@ -314,6 +342,7 @@
mService.loadRebootEscrowDataIfAvailable();
verify(mRebootEscrow).retrieveKey();
assertTrue(metricsSuccessCaptor.getValue());
+ verify(mKeyStoreManager).clearKeyStoreEncryptionKey();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index ac74470..b65e487 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -1074,7 +1074,7 @@
int uid = Binder.getCallingUid();
PendingIntent intent = PendingIntent.getBroadcast(
InstrumentationRegistry.getTargetContext(), /*requestCode=*/1,
- new Intent(), /*flags=*/ 0);
+ new Intent(), /*flags=*/ PendingIntent.FLAG_MUTABLE_UNAUDITED);
mRecoverableKeyStoreManager.setSnapshotCreatedPendingIntent(intent);
verify(mMockListenersStorage).setSnapshotListener(eq(uid), any(PendingIntent.class));
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
index 33038aa..ea3c5fa 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverySnapshotListenersStorageTest.java
@@ -41,7 +41,7 @@
int recoveryAgentUid = 1000;
PendingIntent intent = PendingIntent.getBroadcast(
InstrumentationRegistry.getTargetContext(), /*requestCode=*/ 1,
- new Intent(), /*flags=*/ 0);
+ new Intent(), /*flags=*/ PendingIntent.FLAG_MUTABLE_UNAUDITED);
mStorage.setSnapshotListener(recoveryAgentUid, intent);
assertTrue(mStorage.hasListener(recoveryAgentUid));
@@ -54,7 +54,7 @@
int recoveryAgentUid = 1000;
mStorage.recoverySnapshotAvailable(recoveryAgentUid);
PendingIntent intent = PendingIntent.getBroadcast(
- context, /*requestCode=*/ 0, new Intent(TEST_INTENT_ACTION), /*flags=*/0);
+ context, /*requestCode=*/ 0, new Intent(TEST_INTENT_ACTION), /*flags=*/PendingIntent.FLAG_MUTABLE_UNAUDITED);
CountDownLatch latch = new CountDownLatch(1);
context.registerReceiver(new BroadcastReceiver() {
@Override
@@ -75,7 +75,7 @@
int recoveryAgentUid = 1000;
mStorage.recoverySnapshotAvailable(recoveryAgentUid);
PendingIntent intent = PendingIntent.getBroadcast(
- context, /*requestCode=*/ 0, new Intent(TEST_INTENT_ACTION), /*flags=*/0);
+ context, /*requestCode=*/ 0, new Intent(TEST_INTENT_ACTION), /*flags=*/PendingIntent.FLAG_MUTABLE_UNAUDITED);
CountDownLatch latch = new CountDownLatch(2);
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
index 5468fba..391611b 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -78,7 +78,7 @@
}
@Test
- public void testImmutableEnabledChange() throws Exception {
+ public void testImmutableEnabledChange() {
final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -106,7 +106,7 @@
}
@Test
- public void testMutableEnabledChangeHasNoEffect() throws Exception {
+ public void testMutableEnabledChangeHasNoEffect() {
final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -134,7 +134,7 @@
}
@Test
- public void testMutableEnabledToImmutableEnabled() throws Exception {
+ public void testMutableEnabledToImmutableEnabled() {
final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -178,7 +178,7 @@
}
@Test
- public void testMutablePriorityChange() throws Exception {
+ public void testMutablePriorityChange() {
final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -218,7 +218,7 @@
}
@Test
- public void testImmutablePriorityChange() throws Exception {
+ public void testImmutablePriorityChange() {
final OverlayManagerServiceImpl impl = getImpl();
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER);
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index 33dbcc0..4f882ce 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -22,14 +22,11 @@
import static android.os.OverlayablePolicy.CONFIG_SIGNATURE;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.testng.Assert.assertThrows;
import android.content.om.OverlayInfo;
-import android.util.Pair;
import androidx.test.runner.AndroidJUnit4;
@@ -38,7 +35,6 @@
import java.util.List;
import java.util.Map;
-import java.util.Optional;
@RunWith(AndroidJUnit4.class)
public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase {
@@ -59,7 +55,7 @@
private static final String CERT_CONFIG_NOK = "config_certificate_nok";
@Test
- public void testGetOverlayInfo() throws Exception {
+ public void testGetOverlayInfo() {
installNewPackage(overlay(OVERLAY, TARGET), USER);
final OverlayManagerServiceImpl impl = getImpl();
@@ -71,7 +67,7 @@
}
@Test
- public void testGetOverlayInfosForTarget() throws Exception {
+ public void testGetOverlayInfosForTarget() {
installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER);
installNewPackage(overlay(OVERLAY3, TARGET), USER2);
@@ -96,7 +92,7 @@
}
@Test
- public void testGetOverlayInfosForUser() throws Exception {
+ public void testGetOverlayInfosForUser() {
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER);
@@ -123,7 +119,7 @@
}
@Test
- public void testPriority() throws Exception {
+ public void testPriority() {
installNewPackage(overlay(OVERLAY, TARGET), USER);
installNewPackage(overlay(OVERLAY2, TARGET), USER);
installNewPackage(overlay(OVERLAY3, TARGET), USER);
@@ -135,21 +131,18 @@
assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
- assertEquals(impl.setLowestPriority(OVERLAY3, USER),
- Optional.of(new PackageAndUser(TARGET, USER)));
+ assertTrue(impl.setLowestPriority(OVERLAY3, USER));
assertOverlayInfoForTarget(TARGET, USER, o3, o1, o2);
- assertEquals(impl.setHighestPriority(OVERLAY3, USER),
- Optional.of(new PackageAndUser(TARGET, USER)));
+ assertTrue(impl.setHighestPriority(OVERLAY3, USER));
assertOverlayInfoForTarget(TARGET, USER, o1, o2, o3);
- assertEquals(impl.setPriority(OVERLAY, OVERLAY2, USER),
- Optional.of(new PackageAndUser(TARGET, USER)));
+ assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER));
assertOverlayInfoForTarget(TARGET, USER, o2, o1, o3);
}
@Test
- public void testOverlayInfoStateTransitions() throws Exception {
+ public void testOverlayInfoStateTransitions() {
final OverlayManagerServiceImpl impl = getImpl();
assertNull(impl.getOverlayInfo(OVERLAY, USER));
@@ -160,8 +153,7 @@
installNewPackage(target, USER);
assertState(STATE_DISABLED, OVERLAY, USER);
- assertEquals(impl.setEnabled(OVERLAY, true, USER),
- Optional.of(new PackageAndUser(TARGET, USER)));
+ impl.setEnabled(OVERLAY, true, USER);
assertState(STATE_ENABLED, OVERLAY, USER);
// target upgrades do not change the state of the overlay
@@ -176,40 +168,50 @@
}
@Test
- public void testOnOverlayPackageUpgraded() throws Exception {
+ public void testOnOverlayPackageUpgraded() {
+ final FakeListener listener = getListener();
final FakeDeviceState.PackageBuilder target = target(TARGET);
final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET);
installNewPackage(target, USER);
installNewPackage(overlay, USER);
+ listener.count = 0;
upgradePackage(overlay, USER);
+ assertEquals(2, listener.count);
// upgrade to a version where the overlay has changed its target
+ // expect once for the old target package, once for the new target package
+ listener.count = 0;
final FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target");
- final Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> pair =
- upgradePackage(overlay2, USER);
- assertEquals(pair.first, Optional.of(new PackageAndUser(TARGET, USER)));
- assertEquals(pair.second, Optional.of(new PackageAndUser("some.other.target", USER)));
+ upgradePackage(overlay2, USER);
+ assertEquals(3, listener.count);
+
+ listener.count = 0;
+ upgradePackage(overlay2, USER);
+ assertEquals(2, listener.count);
}
@Test
- public void testSetEnabledAtVariousConditions() throws Exception {
+ public void testListener() {
final OverlayManagerServiceImpl impl = getImpl();
- assertThrows(OverlayManagerServiceImpl.OperationFailedException.class,
- () -> impl.setEnabled(OVERLAY, true, USER));
-
- // request succeeded, and there was a change that needs to be
- // propagated to the rest of the system
- installNewPackage(target(TARGET), USER);
+ final FakeListener listener = getListener();
installNewPackage(overlay(OVERLAY, TARGET), USER);
- assertEquals(impl.setEnabled(OVERLAY, true, USER),
- Optional.of(new PackageAndUser(TARGET, USER)));
+ assertEquals(1, listener.count);
+ listener.count = 0;
- // request succeeded, but nothing changed
- assertFalse(impl.setEnabled(OVERLAY, true, USER).isPresent());
+ installNewPackage(target(TARGET), USER);
+ assertEquals(1, listener.count);
+ listener.count = 0;
+
+ impl.setEnabled(OVERLAY, true, USER);
+ assertEquals(1, listener.count);
+ listener.count = 0;
+
+ impl.setEnabled(OVERLAY, true, USER);
+ assertEquals(0, listener.count);
}
@Test
- public void testConfigSignaturePolicyOk() throws Exception {
+ public void testConfigSignaturePolicyOk() {
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
reinitializeImpl();
@@ -227,7 +229,7 @@
}
@Test
- public void testConfigSignaturePolicyCertNok() throws Exception {
+ public void testConfigSignaturePolicyCertNok() {
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
reinitializeImpl();
@@ -245,7 +247,7 @@
}
@Test
- public void testConfigSignaturePolicyNoConfig() throws Exception {
+ public void testConfigSignaturePolicyNoConfig() {
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
@@ -260,7 +262,7 @@
}
@Test
- public void testConfigSignaturePolicyNoRefPkg() throws Exception {
+ public void testConfigSignaturePolicyNoRefPkg() {
installNewPackage(target(TARGET), USER);
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
@@ -274,7 +276,7 @@
}
@Test
- public void testConfigSignaturePolicyRefPkgNotSystem() throws Exception {
+ public void testConfigSignaturePolicyRefPkgNotSystem() {
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
reinitializeImpl();
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index 2c477c8..006dda0 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -16,8 +16,6 @@
package com.android.server.om;
-import static com.android.server.om.OverlayManagerServiceImpl.OperationFailedException;
-
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
@@ -32,7 +30,6 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.Pair;
import androidx.annotation.Nullable;
@@ -46,13 +43,13 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.stream.Collectors;
/** Base class for creating {@link OverlayManagerServiceImplTests} tests. */
class OverlayManagerServiceImplTestsBase {
private OverlayManagerServiceImpl mImpl;
private FakeDeviceState mState;
+ private FakeListener mListener;
private FakePackageManagerHelper mPackageManager;
private FakeIdmapDaemon mIdmapDaemon;
private OverlayConfig mOverlayConfig;
@@ -61,6 +58,7 @@
@Before
public void setUp() {
mState = new FakeDeviceState();
+ mListener = new FakeListener();
mPackageManager = new FakePackageManagerHelper(mState);
mIdmapDaemon = new FakeIdmapDaemon(mState);
mOverlayConfig = mock(OverlayConfig.class);
@@ -75,13 +73,18 @@
new IdmapManager(mIdmapDaemon, mPackageManager),
new OverlayManagerSettings(),
mOverlayConfig,
- new String[0]);
+ new String[0],
+ mListener);
}
OverlayManagerServiceImpl getImpl() {
return mImpl;
}
+ FakeListener getListener() {
+ return mListener;
+ }
+
FakeIdmapDaemon getIdmapd() {
return mIdmapDaemon;
}
@@ -152,8 +155,7 @@
*
* @throws IllegalStateException if the package is currently installed
*/
- void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId)
- throws OperationFailedException {
+ void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId) {
if (mState.select(pkg.packageName, userId) != null) {
throw new IllegalStateException("package " + pkg.packageName + " already installed");
}
@@ -174,30 +176,23 @@
* {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
* {@link android.content.Intent#EXTRA_REPLACING} extra.
*
- * @return the two Optional<PackageAndUser> objects from starting and finishing the upgrade
- *
* @throws IllegalStateException if the package is not currently installed
*/
- Pair<Optional<PackageAndUser>, Optional<PackageAndUser>> upgradePackage(
- FakeDeviceState.PackageBuilder pkg, int userId) throws OperationFailedException {
+ void upgradePackage(FakeDeviceState.PackageBuilder pkg, int userId) {
final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId);
if (replacedPackage == null) {
throw new IllegalStateException("package " + pkg.packageName + " not installed");
}
- Optional<PackageAndUser> opt1 = Optional.empty();
if (replacedPackage.targetPackageName != null) {
- opt1 = mImpl.onOverlayPackageReplacing(pkg.packageName, userId);
+ mImpl.onOverlayPackageReplacing(pkg.packageName, userId);
}
mState.add(pkg, userId);
- Optional<PackageAndUser> opt2;
if (pkg.targetPackage == null) {
- opt2 = mImpl.onTargetPackageReplaced(pkg.packageName, userId);
+ mImpl.onTargetPackageReplaced(pkg.packageName, userId);
} else {
- opt2 = mImpl.onOverlayPackageReplaced(pkg.packageName, userId);
+ mImpl.onOverlayPackageReplaced(pkg.packageName, userId);
}
-
- return Pair.create(opt1, opt2);
}
/**
@@ -208,7 +203,7 @@
*
* @throws IllegalStateException if the package is not currently installed
*/
- void uninstallPackage(String packageName, int userId) throws OperationFailedException {
+ void uninstallPackage(String packageName, int userId) {
final FakeDeviceState.Package pkg = mState.select(packageName, userId);
if (pkg == null) {
throw new IllegalStateException("package " + packageName+ " not installed");
@@ -490,4 +485,12 @@
}
}
}
+
+ static class FakeListener implements OverlayManagerServiceImpl.OverlayChangeListener {
+ public int count;
+
+ public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
+ count++;
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index be8a99c..63330d5 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -42,12 +42,14 @@
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -141,6 +143,7 @@
@Mock private JobScheduler mJobScheduler;
@Mock private StatusBarNotification mStatusBarNotification;
@Mock private Notification mNotification;
+ @Mock private AlarmManager mAlarmManager;
@Captor private ArgumentCaptor<ShortcutChangeCallback> mShortcutChangeCallbackCaptor;
@Captor private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
@@ -152,7 +155,6 @@
private DataManager mDataManager;
private CancellationSignal mCancellationSignal;
private ShortcutChangeCallback mShortcutChangeCallback;
- private BroadcastReceiver mShutdownBroadcastReceiver;
private ShortcutInfo mShortcutInfo;
private TestInjector mInjector;
@@ -187,10 +189,15 @@
Context originalContext = getInstrumentation().getTargetContext();
when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo());
+ when(mContext.getUser()).thenReturn(originalContext.getUser());
+ when(mContext.getPackageName()).thenReturn(originalContext.getPackageName());
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mContext.getSystemServiceName(UserManager.class)).thenReturn(
Context.USER_SERVICE);
+ when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
+ when(mContext.getSystemServiceName(AlarmManager.class)).thenReturn(
+ Context.ALARM_SERVICE);
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
@@ -246,8 +253,7 @@
mShortcutChangeCallbackCaptor.capture());
mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();
- verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(), any());
- mShutdownBroadcastReceiver = mBroadcastReceiverCaptor.getValue();
+ verify(mContext, times(2)).registerReceiver(any(), any());
}
@After
@@ -767,6 +773,36 @@
}
@Test
+ public void testPruneExpiredConversationStatuses() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ ConversationStatus cs1 = new ConversationStatus.Builder("cs1", 9)
+ .setEndTimeMillis(System.currentTimeMillis())
+ .build();
+ ConversationStatus cs2 = new ConversationStatus.Builder("cs2", 10)
+ .build();
+ ConversationStatus cs3 = new ConversationStatus.Builder("cs3", 1)
+ .setEndTimeMillis(Long.MAX_VALUE)
+ .build();
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs1);
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs3);
+
+ mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
+
+ assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
+ .doesNotContain(cs1);
+ assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
+ .contains(cs2);
+ assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
+ .contains(cs3);
+ }
+
+ @Test
public void testDoNotUncacheShortcutWithActiveNotifications() {
mDataManager.onUserUnlocked(USER_ID_PRIMARY);
NotificationListenerService listenerService =
@@ -976,6 +1012,29 @@
.contains(cs);
assertThat(mDataManager.getStatuses(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID))
.contains(cs2);
+
+ verify(mAlarmManager, never()).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
+ }
+
+ @Test
+ public void testAddOrUpdateStatus_schedulesJob() {
+ mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+ ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+ buildPerson());
+ mDataManager.addOrUpdateConversationInfo(shortcut);
+
+ ConversationStatus cs = new ConversationStatus.Builder("id", ACTIVITY_ANNIVERSARY)
+ .setEndTimeMillis(1000)
+ .build();
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs);
+
+ ConversationStatus cs2 = new ConversationStatus.Builder("id2", ACTIVITY_GAME)
+ .setEndTimeMillis(3000)
+ .build();
+ mDataManager.addOrUpdateStatus(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID, cs2);
+
+ verify(mAlarmManager, times(2)).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index 12e6786..58e00f2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -324,7 +324,7 @@
}
private IntentSender makeResultIntent() {
- return PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0).getIntentSender();
+ return PendingIntent.getActivity(getTestContext(), 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED).getIntentSender();
}
public void testRequestPinShortcut_withCallback() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index c21a3a7..55b4b93 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -147,7 +147,7 @@
public void testRequestPinAppWidget_withCallback() {
final PendingIntent resultIntent =
- PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0);
+ PendingIntent.getActivity(getTestContext(), 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED);
checkRequestPinAppWidget(resultIntent);
}
diff --git a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
index 62be98c..aadab6e 100644
--- a/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/tv/tunerresourcemanager/TunerResourceManagerServiceTest.java
@@ -25,13 +25,14 @@
import android.media.tv.ITvInputManager;
import android.media.tv.TvInputManager;
import android.media.tv.TvInputService;
+import android.media.tv.tuner.TunerFrontendInfo;
import android.media.tv.tuner.frontend.FrontendSettings;
import android.media.tv.tunerresourcemanager.CasSessionRequest;
import android.media.tv.tunerresourcemanager.IResourcesReclaimListener;
import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerCiCamRequest;
import android.media.tv.tunerresourcemanager.TunerDemuxRequest;
import android.media.tv.tunerresourcemanager.TunerDescramblerRequest;
-import android.media.tv.tunerresourcemanager.TunerFrontendInfo;
import android.media.tv.tunerresourcemanager.TunerFrontendRequest;
import android.media.tv.tunerresourcemanager.TunerLnbRequest;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
@@ -86,9 +87,9 @@
return (actual == null) && (expected == null);
}
- return actual.getHandle() == expected.getHandle()
- && actual.getType() == expected.getFrontendType()
- && actual.getExclusiveGroupId() == expected.getExclusiveGroupId();
+ return actual.getHandle() == expected.handle
+ && actual.getType() == expected.type
+ && actual.getExclusiveGroupId() == expected.exclusiveGroupId;
}, "is correctly configured from ");
@Before
@@ -99,7 +100,7 @@
when(mContextSpy.getSystemService(Context.TV_INPUT_SERVICE)).thenReturn(tvInputManager);
mTunerResourceManagerService = new TunerResourceManagerService(mContextSpy) {
@Override
- protected boolean isForeground(int pid) {
+ protected boolean checkIsForeground(int pid) {
return mIsForeground;
}
};
@@ -111,19 +112,19 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[2];
infos[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
infos[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
Map<Integer, FrontendResource> resources =
mTunerResourceManagerService.getFrontendResources();
for (int id = 0; id < infos.length; id++) {
- assertThat(resources.get(infos[id].getHandle())
+ assertThat(resources.get(infos[id].handle)
.getExclusiveGroupMemberFeHandles().size()).isEqualTo(0);
}
for (int id = 0; id < infos.length; id++) {
- assertThat(resources.get(infos[id].getHandle())
+ assertThat(resources.get(infos[id].handle)
.getExclusiveGroupMemberFeHandles().size()).isEqualTo(0);
}
assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE)
@@ -135,13 +136,13 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[4];
infos[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
infos[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
infos[2] =
- new TunerFrontendInfo(2 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(2 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
infos[3] =
- new TunerFrontendInfo(3 /*id*/, FrontendSettings.TYPE_ATSC, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(3 /*handle*/, FrontendSettings.TYPE_ATSC, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
Map<Integer, FrontendResource> resources =
@@ -160,9 +161,9 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[2];
infos[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
infos[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
Map<Integer, FrontendResource> resources0 =
@@ -180,22 +181,22 @@
// Init frontend resources.
TunerFrontendInfo[] infos0 = new TunerFrontendInfo[3];
infos0[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
infos0[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
infos0[2] =
- new TunerFrontendInfo(2 /*id*/, FrontendSettings.TYPE_DVBS, 2 /*exclusiveGroupId*/);
+ tunerFrontendInfo(2 /*handle*/, FrontendSettings.TYPE_DVBS, 2 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos0);
TunerFrontendInfo[] infos1 = new TunerFrontendInfo[1];
infos1[0] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos1);
Map<Integer, FrontendResource> resources =
mTunerResourceManagerService.getFrontendResources();
for (int id = 0; id < infos1.length; id++) {
- assertThat(resources.get(infos1[id].getHandle())
+ assertThat(resources.get(infos1[id].handle)
.getExclusiveGroupMemberFeHandles().size()).isEqualTo(0);
}
assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE)
@@ -207,22 +208,22 @@
// Init frontend resources.
TunerFrontendInfo[] infos0 = new TunerFrontendInfo[3];
infos0[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
infos0[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
infos0[2] =
- new TunerFrontendInfo(2 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(2 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos0);
TunerFrontendInfo[] infos1 = new TunerFrontendInfo[1];
infos1[0] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos1);
Map<Integer, FrontendResource> resources =
mTunerResourceManagerService.getFrontendResources();
for (int id = 0; id < infos1.length; id++) {
- assertThat(resources.get(infos1[id].getHandle())
+ assertThat(resources.get(infos1[id].handle)
.getExclusiveGroupMemberFeHandles().size()).isEqualTo(0);
}
assertThat(resources.values()).comparingElementsUsing(FR_TFI_COMPARE)
@@ -231,8 +232,12 @@
@Test
public void requestFrontendTest_ClientNotRegistered() {
+ TunerFrontendInfo[] infos0 = new TunerFrontendInfo[1];
+ infos0[0] =
+ tunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 0 /*exclusiveGroupId*/);
+ mTunerResourceManagerService.setFrontendInfoListInternal(infos0);
TunerFrontendRequest request =
- new TunerFrontendRequest(0 /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(0 /*clientId*/, FrontendSettings.TYPE_DVBT);
int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isFalse();
@@ -241,7 +246,7 @@
@Test
public void requestFrontendTest_NoFrontendWithGiveTypeAvailable() {
- ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/,
+ ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId = new int[1];
mTunerResourceManagerService.registerClientProfileInternal(
@@ -251,11 +256,11 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[1];
infos[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBS, 0 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBS, 0 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
TunerFrontendRequest request =
- new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isFalse();
@@ -264,7 +269,7 @@
@Test
public void requestFrontendTest_FrontendWithNoExclusiveGroupAvailable() {
- ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/,
+ ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId = new int[1];
mTunerResourceManagerService.registerClientProfileInternal(
@@ -273,22 +278,22 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[3];
- infos[0] = new TunerFrontendInfo(
+ infos[0] = tunerFrontendInfo(
0 /*handle*/,
FrontendSettings.TYPE_DVBT,
0 /*exclusiveGroupId*/);
- infos[1] = new TunerFrontendInfo(
+ infos[1] = tunerFrontendInfo(
1 /*handle*/,
FrontendSettings.TYPE_DVBT,
1 /*exclusiveGroupId*/);
- infos[2] = new TunerFrontendInfo(
+ infos[2] = tunerFrontendInfo(
2 /*handle*/,
FrontendSettings.TYPE_DVBS,
1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
TunerFrontendRequest request =
- new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
@@ -297,9 +302,9 @@
@Test
public void requestFrontendTest_FrontendWithExclusiveGroupAvailable() {
- ResourceClientProfile profile0 = new ResourceClientProfile("0" /*sessionId*/,
+ ResourceClientProfile profile0 = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
- ResourceClientProfile profile1 = new ResourceClientProfile("1" /*sessionId*/,
+ ResourceClientProfile profile1 = resourceClientProfile("1" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId0 = new int[1];
int[] clientId1 = new int[1];
@@ -312,15 +317,15 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[3];
- infos[0] = new TunerFrontendInfo(
+ infos[0] = tunerFrontendInfo(
0 /*handle*/,
FrontendSettings.TYPE_DVBT,
0 /*exclusiveGroupId*/);
- infos[1] = new TunerFrontendInfo(
+ infos[1] = tunerFrontendInfo(
1 /*handle*/,
FrontendSettings.TYPE_DVBT,
1 /*exclusiveGroupId*/);
- infos[2] = new TunerFrontendInfo(
+ infos[2] = tunerFrontendInfo(
2 /*handle*/,
FrontendSettings.TYPE_DVBS,
1 /*exclusiveGroupId*/);
@@ -328,19 +333,19 @@
int[] frontendHandle = new int[1];
TunerFrontendRequest request =
- new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
- assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle());
+ assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
request =
- new TunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
- assertThat(frontendHandle[0]).isEqualTo(infos[1].getHandle());
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle()).isInUse())
+ assertThat(frontendHandle[0]).isEqualTo(infos[1].handle);
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle).isInUse())
.isTrue();
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[2].getHandle()).isInUse())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[2].handle).isInUse())
.isTrue();
}
@@ -348,9 +353,9 @@
public void requestFrontendTest_NoFrontendAvailable_RequestWithLowerPriority() {
// Register clients
ResourceClientProfile[] profiles = new ResourceClientProfile[2];
- profiles[0] = new ResourceClientProfile("0" /*sessionId*/,
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
- profiles[1] = new ResourceClientProfile("1" /*sessionId*/,
+ profiles[1] = resourceClientProfile("1" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientPriorities = {100, 50};
int[] clientId0 = new int[1];
@@ -371,25 +376,25 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[2];
infos[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
infos[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
TunerFrontendRequest request =
- new TunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
request =
- new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isFalse();
assertThat(listener.isReclaimed()).isFalse();
request =
- new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS);
+ tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS);
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isFalse();
assertThat(listener.isReclaimed()).isFalse();
@@ -399,9 +404,9 @@
public void requestFrontendTest_NoFrontendAvailable_RequestWithHigherPriority() {
// Register clients
ResourceClientProfile[] profiles = new ResourceClientProfile[2];
- profiles[0] = new ResourceClientProfile("0" /*sessionId*/,
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
- profiles[1] = new ResourceClientProfile("1" /*sessionId*/,
+ profiles[1] = resourceClientProfile("1" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientPriorities = {100, 500};
int[] clientId0 = new int[1];
@@ -421,33 +426,33 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[2];
infos[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
infos[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
TunerFrontendRequest request =
- new TunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId0[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
- assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle());
+ assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0])
.getInUseFrontendHandles()).isEqualTo(new HashSet<Integer>(Arrays.asList(
- infos[0].getHandle(), infos[1].getHandle())));
+ infos[0].handle, infos[1].handle)));
request =
- new TunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS);
+ tunerFrontendRequest(clientId1[0] /*clientId*/, FrontendSettings.TYPE_DVBS);
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
- assertThat(frontendHandle[0]).isEqualTo(infos[1].getHandle());
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(frontendHandle[0]).isEqualTo(infos[1].handle);
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.isInUse()).isTrue();
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.isInUse()).isTrue();
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.getOwnerClientId()).isEqualTo(clientId1[0]);
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.getOwnerClientId()).isEqualTo(clientId1[0]);
assertThat(listener.isReclaimed()).isTrue();
}
@@ -456,7 +461,7 @@
public void releaseFrontendTest_UnderTheSameExclusiveGroup() {
// Register clients
ResourceClientProfile[] profiles = new ResourceClientProfile[1];
- profiles[0] = new ResourceClientProfile("0" /*sessionId*/,
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId = new int[1];
TestResourcesReclaimListener listener = new TestResourcesReclaimListener();
@@ -466,19 +471,19 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[2];
infos[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
infos[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
TunerFrontendRequest request =
- new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
- assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle());
+ assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
assertThat(mTunerResourceManagerService
- .getFrontendResource(infos[1].getHandle()).isInUse()).isTrue();
+ .getFrontendResource(infos[1].handle).isInUse()).isTrue();
// Release frontend
mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService
@@ -486,7 +491,7 @@
assertThat(mTunerResourceManagerService
.getFrontendResource(frontendHandle[0]).isInUse()).isFalse();
assertThat(mTunerResourceManagerService
- .getFrontendResource(infos[1].getHandle()).isInUse()).isFalse();
+ .getFrontendResource(infos[1].handle).isInUse()).isFalse();
assertThat(mTunerResourceManagerService
.getClientProfile(clientId[0]).getInUseFrontendHandles().size()).isEqualTo(0);
}
@@ -495,9 +500,9 @@
public void requestCasTest_NoCasAvailable_RequestWithHigherPriority() {
// Register clients
ResourceClientProfile[] profiles = new ResourceClientProfile[2];
- profiles[0] = new ResourceClientProfile("0" /*sessionId*/,
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
- profiles[1] = new ResourceClientProfile("1" /*sessionId*/,
+ profiles[1] = resourceClientProfile("1" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientPriorities = {100, 500};
int[] clientId0 = new int[1];
@@ -517,7 +522,7 @@
// Init cas resources.
mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/);
- CasSessionRequest request = new CasSessionRequest(clientId0[0], 1 /*casSystemId*/);
+ CasSessionRequest request = casSessionRequest(clientId0[0], 1 /*casSystemId*/);
int[] casSessionHandle = new int[1];
// Request for 2 cas sessions.
assertThat(mTunerResourceManagerService
@@ -532,7 +537,7 @@
.getOwnerClientIds()).isEqualTo(new HashSet<Integer>(Arrays.asList(clientId0[0])));
assertThat(mTunerResourceManagerService.getCasResource(1).isFullyUsed()).isTrue();
- request = new CasSessionRequest(clientId1[0], 1);
+ request = casSessionRequest(clientId1[0], 1);
assertThat(mTunerResourceManagerService
.requestCasSessionInternal(request, casSessionHandle)).isTrue();
assertThat(mTunerResourceManagerService.getResourceIdFromHandle(casSessionHandle[0]))
@@ -548,10 +553,66 @@
}
@Test
+ public void requestCiCamTest_NoCiCamAvailable_RequestWithHigherPriority() {
+ // Register clients
+ ResourceClientProfile[] profiles = new ResourceClientProfile[2];
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
+ TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
+ profiles[1] = resourceClientProfile("1" /*sessionId*/,
+ TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
+ int[] clientPriorities = {100, 500};
+ int[] clientId0 = new int[1];
+ int[] clientId1 = new int[1];
+ TestResourcesReclaimListener listener = new TestResourcesReclaimListener();
+ mTunerResourceManagerService.registerClientProfileInternal(
+ profiles[0], listener, clientId0);
+ assertThat(clientId0[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
+ mTunerResourceManagerService.getClientProfile(clientId0[0])
+ .setPriority(clientPriorities[0]);
+ mTunerResourceManagerService.registerClientProfileInternal(
+ profiles[1], new TestResourcesReclaimListener(), clientId1);
+ assertThat(clientId1[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
+ mTunerResourceManagerService.getClientProfile(clientId1[0])
+ .setPriority(clientPriorities[1]);
+
+ // Init cicam/cas resources.
+ mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/);
+
+ TunerCiCamRequest request = tunerCiCamRequest(clientId0[0], 1 /*ciCamId*/);
+ int[] ciCamHandle = new int[1];
+ // Request for 2 ciCam sessions.
+ assertThat(mTunerResourceManagerService
+ .requestCiCamInternal(request, ciCamHandle)).isTrue();
+ assertThat(mTunerResourceManagerService
+ .requestCiCamInternal(request, ciCamHandle)).isTrue();
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(ciCamHandle[0]))
+ .isEqualTo(1);
+ assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0])
+ .getInUseCiCamId()).isEqualTo(1);
+ assertThat(mTunerResourceManagerService.getCiCamResource(1)
+ .getOwnerClientIds()).isEqualTo(new HashSet<Integer>(Arrays.asList(clientId0[0])));
+ assertThat(mTunerResourceManagerService.getCiCamResource(1).isFullyUsed()).isTrue();
+
+ request = tunerCiCamRequest(clientId1[0], 1);
+ assertThat(mTunerResourceManagerService
+ .requestCiCamInternal(request, ciCamHandle)).isTrue();
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(ciCamHandle[0]))
+ .isEqualTo(1);
+ assertThat(mTunerResourceManagerService.getClientProfile(clientId1[0])
+ .getInUseCiCamId()).isEqualTo(1);
+ assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0])
+ .getInUseCiCamId()).isEqualTo(ClientProfile.INVALID_RESOURCE_ID);
+ assertThat(mTunerResourceManagerService.getCiCamResource(1)
+ .getOwnerClientIds()).isEqualTo(new HashSet<Integer>(Arrays.asList(clientId1[0])));
+ assertThat(mTunerResourceManagerService.getCiCamResource(1).isFullyUsed()).isFalse();
+ assertThat(listener.isReclaimed()).isTrue();
+ }
+
+ @Test
public void releaseCasTest() {
// Register clients
ResourceClientProfile[] profiles = new ResourceClientProfile[1];
- profiles[0] = new ResourceClientProfile("0" /*sessionId*/,
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId = new int[1];
TestResourcesReclaimListener listener = new TestResourcesReclaimListener();
@@ -561,7 +622,7 @@
// Init cas resources.
mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/);
- CasSessionRequest request = new CasSessionRequest(clientId[0], 1 /*casSystemId*/);
+ CasSessionRequest request = casSessionRequest(clientId[0], 1 /*casSystemId*/);
int[] casSessionHandle = new int[1];
// Request for 1 cas sessions.
assertThat(mTunerResourceManagerService
@@ -585,12 +646,49 @@
}
@Test
+ public void releaseCiCamTest() {
+ // Register clients
+ ResourceClientProfile[] profiles = new ResourceClientProfile[1];
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
+ TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
+ int[] clientId = new int[1];
+ TestResourcesReclaimListener listener = new TestResourcesReclaimListener();
+ mTunerResourceManagerService.registerClientProfileInternal(profiles[0], listener, clientId);
+ assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
+
+ // Init cas resources.
+ mTunerResourceManagerService.updateCasInfoInternal(1 /*casSystemId*/, 2 /*maxSessionNum*/);
+
+ TunerCiCamRequest request = tunerCiCamRequest(clientId[0], 1 /*ciCamId*/);
+ int[] ciCamHandle = new int[1];
+ // Request for 1 ciCam sessions.
+ assertThat(mTunerResourceManagerService
+ .requestCiCamInternal(request, ciCamHandle)).isTrue();
+ assertThat(mTunerResourceManagerService.getResourceIdFromHandle(ciCamHandle[0]))
+ .isEqualTo(1);
+ assertThat(mTunerResourceManagerService.getClientProfile(clientId[0])
+ .getInUseCiCamId()).isEqualTo(1);
+ assertThat(mTunerResourceManagerService.getCiCamResource(1)
+ .getOwnerClientIds()).isEqualTo(new HashSet<Integer>(Arrays.asList(clientId[0])));
+ assertThat(mTunerResourceManagerService.getCiCamResource(1).isFullyUsed()).isFalse();
+
+ // Release ciCam
+ mTunerResourceManagerService.releaseCiCamInternal(mTunerResourceManagerService
+ .getCiCamResource(1), clientId[0]);
+ assertThat(mTunerResourceManagerService.getClientProfile(clientId[0])
+ .getInUseCiCamId()).isEqualTo(ClientProfile.INVALID_RESOURCE_ID);
+ assertThat(mTunerResourceManagerService.getCiCamResource(1).isFullyUsed()).isFalse();
+ assertThat(mTunerResourceManagerService.getCiCamResource(1)
+ .getOwnerClientIds()).isEmpty();
+ }
+
+ @Test
public void requestLnbTest_NoLnbAvailable_RequestWithHigherPriority() {
// Register clients
ResourceClientProfile[] profiles = new ResourceClientProfile[2];
- profiles[0] = new ResourceClientProfile("0" /*sessionId*/,
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
- profiles[1] = new ResourceClientProfile("1" /*sessionId*/,
+ profiles[1] = resourceClientProfile("1" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientPriorities = {100, 500};
int[] clientId0 = new int[1];
@@ -611,7 +709,8 @@
int[] lnbHandles = {1};
mTunerResourceManagerService.setLnbInfoListInternal(lnbHandles);
- TunerLnbRequest request = new TunerLnbRequest(clientId0[0]);
+ TunerLnbRequest request = new TunerLnbRequest();
+ request.clientId = clientId0[0];
int[] lnbHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestLnbInternal(request, lnbHandle)).isTrue();
@@ -619,7 +718,9 @@
assertThat(mTunerResourceManagerService.getClientProfile(clientId0[0]).getInUseLnbHandles())
.isEqualTo(new HashSet<Integer>(Arrays.asList(lnbHandles[0])));
- request = new TunerLnbRequest(clientId1[0]);
+ request = new TunerLnbRequest();
+ request.clientId = clientId1[0];
+
assertThat(mTunerResourceManagerService
.requestLnbInternal(request, lnbHandle)).isTrue();
assertThat(lnbHandle[0]).isEqualTo(lnbHandles[0]);
@@ -636,7 +737,7 @@
public void releaseLnbTest() {
// Register clients
ResourceClientProfile[] profiles = new ResourceClientProfile[1];
- profiles[0] = new ResourceClientProfile("0" /*sessionId*/,
+ profiles[0] = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId = new int[1];
TestResourcesReclaimListener listener = new TestResourcesReclaimListener();
@@ -647,7 +748,8 @@
int[] lnbHandles = {0};
mTunerResourceManagerService.setLnbInfoListInternal(lnbHandles);
- TunerLnbRequest request = new TunerLnbRequest(clientId[0]);
+ TunerLnbRequest request = new TunerLnbRequest();
+ request.clientId = clientId[0];
int[] lnbHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestLnbInternal(request, lnbHandle)).isTrue();
@@ -665,7 +767,7 @@
@Test
public void unregisterClientTest_usingFrontend() {
// Register client
- ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/,
+ ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId = new int[1];
mTunerResourceManagerService.registerClientProfileInternal(
@@ -675,27 +777,27 @@
// Init frontend resources.
TunerFrontendInfo[] infos = new TunerFrontendInfo[2];
infos[0] =
- new TunerFrontendInfo(0 /*id*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(0 /*handle*/, FrontendSettings.TYPE_DVBT, 1 /*exclusiveGroupId*/);
infos[1] =
- new TunerFrontendInfo(1 /*id*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
+ tunerFrontendInfo(1 /*handle*/, FrontendSettings.TYPE_DVBS, 1 /*exclusiveGroupId*/);
mTunerResourceManagerService.setFrontendInfoListInternal(infos);
TunerFrontendRequest request =
- new TunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
+ tunerFrontendRequest(clientId[0] /*clientId*/, FrontendSettings.TYPE_DVBT);
int[] frontendHandle = new int[1];
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle)).isTrue();
- assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle());
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.isInUse()).isTrue();
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.isInUse()).isTrue();
// Unregister client when using frontend
mTunerResourceManagerService.unregisterClientProfileInternal(clientId[0]);
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.isInUse()).isFalse();
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.isInUse()).isFalse();
assertThat(mTunerResourceManagerService.checkClientExists(clientId[0])).isFalse();
@@ -704,7 +806,7 @@
@Test
public void requestDemuxTest() {
// Register client
- ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/,
+ ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId = new int[1];
mTunerResourceManagerService.registerClientProfileInternal(
@@ -712,7 +814,8 @@
assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
int[] demuxHandle = new int[1];
- TunerDemuxRequest request = new TunerDemuxRequest(clientId[0]);
+ TunerDemuxRequest request = new TunerDemuxRequest();
+ request.clientId = clientId[0];
assertThat(mTunerResourceManagerService.requestDemuxInternal(request, demuxHandle))
.isTrue();
assertThat(mTunerResourceManagerService.getResourceIdFromHandle(demuxHandle[0]))
@@ -722,7 +825,7 @@
@Test
public void requestDescramblerTest() {
// Register client
- ResourceClientProfile profile = new ResourceClientProfile("0" /*sessionId*/,
+ ResourceClientProfile profile = resourceClientProfile("0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
int[] clientId = new int[1];
mTunerResourceManagerService.registerClientProfileInternal(
@@ -730,7 +833,8 @@
assertThat(clientId[0]).isNotEqualTo(TunerResourceManagerService.INVALID_CLIENT_ID);
int[] desHandle = new int[1];
- TunerDescramblerRequest request = new TunerDescramblerRequest(clientId[0]);
+ TunerDescramblerRequest request = new TunerDescramblerRequest();
+ request.clientId = clientId[0];
assertThat(mTunerResourceManagerService.requestDescramblerInternal(request, desHandle))
.isTrue();
assertThat(mTunerResourceManagerService.getResourceIdFromHandle(desHandle[0])).isEqualTo(0);
@@ -740,15 +844,15 @@
public void isHigherPriorityTest() {
mIsForeground = false;
ResourceClientProfile backgroundPlaybackProfile =
- new ResourceClientProfile(null /*sessionId*/,
+ resourceClientProfile(null /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK);
ResourceClientProfile backgroundRecordProfile =
- new ResourceClientProfile(null /*sessionId*/,
+ resourceClientProfile(null /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD);
int backgroundPlaybackPriority = mTunerResourceManagerService.getClientPriority(
- TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK, 0);
+ TvInputService.PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK, mIsForeground);
int backgroundRecordPriority = mTunerResourceManagerService.getClientPriority(
- TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD, 0);
+ TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD, mIsForeground);
assertThat(mTunerResourceManagerService.isHigherPriorityInternal(backgroundPlaybackProfile,
backgroundRecordProfile)).isEqualTo(
(backgroundPlaybackPriority > backgroundRecordPriority));
@@ -767,16 +871,16 @@
// Predefined client profiles
ResourceClientProfile[] ownerProfiles = new ResourceClientProfile[2];
ResourceClientProfile[] shareProfiles = new ResourceClientProfile[2];
- ownerProfiles[0] = new ResourceClientProfile(
+ ownerProfiles[0] = resourceClientProfile(
"0" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE);
- ownerProfiles[1] = new ResourceClientProfile(
+ ownerProfiles[1] = resourceClientProfile(
"1" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_LIVE);
- shareProfiles[0] = new ResourceClientProfile(
+ shareProfiles[0] = resourceClientProfile(
"2" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD);
- shareProfiles[1] = new ResourceClientProfile(
+ shareProfiles[1] = resourceClientProfile(
"3" /*sessionId*/,
TvInputService.PRIORITY_HINT_USE_CASE_TYPE_RECORD);
@@ -828,12 +932,12 @@
// Predefined frontend info
TunerFrontendInfo[] infos = new TunerFrontendInfo[2];
- infos[0] = new TunerFrontendInfo(
- 0 /*id*/,
+ infos[0] = tunerFrontendInfo(
+ 0 /*handle*/,
FrontendSettings.TYPE_DVBT,
1 /*exclusiveGroupId*/);
- infos[1] = new TunerFrontendInfo(
- 1 /*id*/,
+ infos[1] = tunerFrontendInfo(
+ 1 /*handle*/,
FrontendSettings.TYPE_DVBS,
1 /*exclusiveGroupId*/);
@@ -848,7 +952,7 @@
// Predefined frontend request and array to save returned frontend handle
int[] frontendHandle = new int[1];
- TunerFrontendRequest request = new TunerFrontendRequest(
+ TunerFrontendRequest request = tunerFrontendRequest(
ownerClientId0[0] /*clientId*/,
FrontendSettings.TYPE_DVBT);
@@ -856,13 +960,13 @@
assertThat(mTunerResourceManagerService
.requestFrontendInternal(request, frontendHandle))
.isTrue();
- assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle());
+ assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
assertThat(mTunerResourceManagerService
.getClientProfile(ownerClientId0[0])
.getInUseFrontendHandles())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
- infos[0].getHandle(),
- infos[1].getHandle())));
+ infos[0].handle,
+ infos[1].handle)));
/**** Share Frontend ****/
@@ -874,14 +978,14 @@
shareClientId1[0]/*selfClientId*/,
ownerClientId0[0]/*targetClientId*/);
// Verify fe in use status
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.isInUse()).isTrue();
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.isInUse()).isTrue();
// Verify fe owner status
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.getOwnerClientId()).isEqualTo(ownerClientId0[0]);
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.getOwnerClientId()).isEqualTo(ownerClientId0[0]);
// Verify share fe client status in the primary owner client
assertThat(mTunerResourceManagerService.getClientProfile(ownerClientId0[0])
@@ -894,20 +998,20 @@
.getClientProfile(ownerClientId0[0])
.getInUseFrontendHandles())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
- infos[0].getHandle(),
- infos[1].getHandle())));
+ infos[0].handle,
+ infos[1].handle)));
assertThat(mTunerResourceManagerService
.getClientProfile(shareClientId0[0])
.getInUseFrontendHandles())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
- infos[0].getHandle(),
- infos[1].getHandle())));
+ infos[0].handle,
+ infos[1].handle)));
assertThat(mTunerResourceManagerService
.getClientProfile(shareClientId1[0])
.getInUseFrontendHandles())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
- infos[0].getHandle(),
- infos[1].getHandle())));
+ infos[0].handle,
+ infos[1].handle)));
/**** Remove Frontend Share Owner ****/
@@ -923,19 +1027,19 @@
.getClientProfile(ownerClientId0[0])
.getInUseFrontendHandles())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
- infos[0].getHandle(),
- infos[1].getHandle())));
+ infos[0].handle,
+ infos[1].handle)));
assertThat(mTunerResourceManagerService
.getClientProfile(shareClientId0[0])
.getInUseFrontendHandles())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
- infos[0].getHandle(),
- infos[1].getHandle())));
+ infos[0].handle,
+ infos[1].handle)));
/**** Request Shared Frontend with Higher Priority Client ****/
// Predefined second frontend request
- request = new TunerFrontendRequest(
+ request = tunerFrontendRequest(
ownerClientId1[0] /*clientId*/,
FrontendSettings.TYPE_DVBT);
@@ -945,17 +1049,17 @@
.isTrue();
// Validate granted resource and internal mapping
- assertThat(frontendHandle[0]).isEqualTo(infos[0].getHandle());
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(frontendHandle[0]).isEqualTo(infos[0].handle);
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.getOwnerClientId()).isEqualTo(ownerClientId1[0]);
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.getOwnerClientId()).isEqualTo(ownerClientId1[0]);
assertThat(mTunerResourceManagerService
.getClientProfile(ownerClientId1[0])
.getInUseFrontendHandles())
.isEqualTo(new HashSet<Integer>(Arrays.asList(
- infos[0].getHandle(),
- infos[1].getHandle())));
+ infos[0].handle,
+ infos[1].handle)));
assertThat(mTunerResourceManagerService
.getClientProfile(ownerClientId0[0])
.getInUseFrontendHandles()
@@ -983,12 +1087,12 @@
// Release the frontend resource from the primary owner
mTunerResourceManagerService.releaseFrontendInternal(mTunerResourceManagerService
- .getFrontendResource(infos[0].getHandle()), ownerClientId1[0]);
+ .getFrontendResource(infos[0].handle), ownerClientId1[0]);
// Validate the internal mapping
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.isInUse()).isFalse();
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.isInUse()).isFalse();
// Verify client status
assertThat(mTunerResourceManagerService
@@ -1010,7 +1114,8 @@
/**** Unregister Primary Owner when the Share owner owns an Lnb ****/
// Predefined Lnb request and handle array
- TunerLnbRequest requestLnb = new TunerLnbRequest(shareClientId0[0]);
+ TunerLnbRequest requestLnb = new TunerLnbRequest();
+ requestLnb.clientId = shareClientId0[0];
int[] lnbHandle = new int[1];
// Request for an Lnb
@@ -1030,9 +1135,9 @@
mTunerResourceManagerService.unregisterClientProfileInternal(ownerClientId1[0]);
// Validate the internal mapping
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[0].handle)
.isInUse()).isFalse();
- assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].getHandle())
+ assertThat(mTunerResourceManagerService.getFrontendResource(infos[1].handle)
.isInUse()).isFalse();
// Verify client status
assertThat(mTunerResourceManagerService
@@ -1046,4 +1151,41 @@
.isEqualTo(new HashSet<Integer>(Arrays.asList(
lnbHandles[0])));
}
+
+ private TunerFrontendInfo tunerFrontendInfo(
+ int handle, int frontendType, int exclusiveGroupId) {
+ TunerFrontendInfo info = new TunerFrontendInfo();
+ info.handle = handle;
+ info.type = frontendType;
+ info.exclusiveGroupId = exclusiveGroupId;
+ return info;
+ }
+
+ private TunerFrontendRequest tunerFrontendRequest(int clientId, int frontendType) {
+ TunerFrontendRequest request = new TunerFrontendRequest();
+ request.clientId = clientId;
+ request.frontendType = frontendType;
+ return request;
+ }
+
+ private ResourceClientProfile resourceClientProfile(String sessionId, int useCase) {
+ ResourceClientProfile profile = new ResourceClientProfile();
+ profile.tvInputSessionId = sessionId;
+ profile.useCase = useCase;
+ return profile;
+ }
+
+ private CasSessionRequest casSessionRequest(int clientId, int casSystemId) {
+ CasSessionRequest request = new CasSessionRequest();
+ request.clientId = clientId;
+ request.casSystemId = casSystemId;
+ return request;
+ }
+
+ private TunerCiCamRequest tunerCiCamRequest(int clientId, int ciCamId) {
+ TunerCiCamRequest request = new TunerCiCamRequest();
+ request.clientId = clientId;
+ request.ciCamId = ciCamId;
+ return request;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
index 7c65dc0..b40d59c 100644
--- a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
@@ -254,6 +254,8 @@
tester.verify(15, "Tick after snapshot");
// Verify that the snapshot is sealed
verifySealed(name, ()->arraySnap.put(INDEX_A, leafA));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Recreate the snapshot since the test corrupted it.
{
@@ -355,6 +357,8 @@
tester.verify(16, "Tick after snapshot");
// Verify that the array snapshot is sealed
verifySealed(name, ()->arraySnap.add(leafB));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Recreate the snapshot since the test corrupted it.
{
@@ -467,6 +471,8 @@
tester.verify(20, "Tick after snapshot");
// Verify that the array snapshot is sealed
verifySealed(name, ()->arraySnap.add(indexA, leafB));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Recreate the snapshot since the test corrupted it.
{
@@ -586,6 +592,8 @@
tester.verify(23, "Tick after snapshot");
// Verify that the array snapshot is sealed
verifySealed(name, ()->arraySnap.put(INDEX_A, leafB));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Recreate the snapshot since the test corrupted it.
{
@@ -649,6 +657,8 @@
tester.verify(6, "Tick after snapshot");
// Verify that the array is sealed
verifySealed(name, ()->arraySnap.put(INDEX_D, false));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Verify copy-in/out
{
@@ -705,6 +715,8 @@
tester.verify(6, "Tick after snapshot");
// Verify that the array is sealed
verifySealed(name, ()->arraySnap.put(INDEX_D, 10));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
}
// Verify copy-in/out
{
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index ecdb8bc..1e112da 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -36,7 +37,6 @@
import android.os.Handler;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
@@ -229,9 +229,23 @@
}
@Test
- public void shouldVibrateForUid_withBackgroundAllowedUsage_returnTrue() throws RemoteException {
+ public void shouldVibrateForUid_withForegroundOnlyUsage_returnsTrueWhInForeground() {
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_TOUCH));
+
+ mVibrationSettings.mUidObserver.onUidStateChanged(
+ UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
+ assertFalse(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_TOUCH));
+ }
+
+ @Test
+ public void shouldVibrateForUid_withBackgroundAllowedUsage_returnTrue() {
+ mVibrationSettings.mUidObserver.onUidStateChanged(
+ UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
+
assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_ALARM));
assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
+ VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+ assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
VibrationAttributes.USAGE_NOTIFICATION));
assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_RINGTONE));
}
@@ -377,5 +391,4 @@
mAudioManager.setRingerModeInternal(ringerMode);
assertEquals(ringerMode, mAudioManager.getRingerModeInternal());
}
-
}
diff --git a/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobActivity.java b/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobActivity.java
index 884ba70..99eb196 100644
--- a/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobActivity.java
+++ b/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobActivity.java
@@ -50,7 +50,8 @@
final int jobId = intent.getIntExtra(EXTRA_JOB_ID_KEY, hashCode());
JobInfo.Builder jobBuilder = new JobInfo.Builder(jobId, jobServiceComponent)
.setBackoffCriteria(JOB_INITIAL_BACKOFF, JobInfo.BACKOFF_POLICY_LINEAR)
- .setMinimumLatency(JOB_MINIMUM_LATENCY);
+ .setMinimumLatency(JOB_MINIMUM_LATENCY)
+ .setOverrideDeadline(JOB_MINIMUM_LATENCY);
final int result = jobScheduler.schedule(jobBuilder.build());
if (result != JobScheduler.RESULT_SUCCESS) {
Log.e(TAG, "Could not schedule job " + jobId);
diff --git a/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobService.java b/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobService.java
index 6bebb32..3e79407 100644
--- a/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobService.java
+++ b/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobService.java
@@ -45,6 +45,7 @@
Intent reportJobStopIntent = new Intent(ACTION_JOB_STOPPED);
reportJobStopIntent.putExtra(JOB_PARAMS_EXTRA_KEY, params);
sendBroadcast(reportJobStopIntent);
- return true;
+ // Deadline constraint is dropped on reschedule, so it's more reliable to use a new job.
+ return false;
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index bd622e1..35876e4 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6531,9 +6531,8 @@
Notification notif = mService.getNotificationRecord(nr.getSbn().getKey()).getNotification();
assertTrue(notif.isBubbleNotification());
- // Our flags should have failed since we're not foreground
+ // The flag should have failed since we're not foreground
assertFalse(notif.getBubbleMetadata().getAutoExpandBubble());
- assertFalse(notif.getBubbleMetadata().isNotificationSuppressed());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index f1dc098..6b69ee9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -351,6 +351,22 @@
}
@Test
+ public void testActivityDrawnBeforeTransition() {
+ mTopActivity.setVisible(false);
+ notifyActivityLaunching(mTopActivity.intent);
+ // Assume the activity is launched the second time consecutively. The drawn event is from
+ // the first time (omitted in test) launch that is earlier than transition.
+ doReturn(true).when(mTopActivity).isReportedDrawn();
+ notifyWindowsDrawn(mTopActivity);
+ notifyActivityLaunched(START_SUCCESS, mTopActivity);
+ // If the launching activity was drawn when starting transition, the launch event should
+ // be reported successfully.
+ notifyTransitionStarting(mTopActivity);
+
+ verifyOnActivityLaunchFinished(mTopActivity);
+ }
+
+ @Test
public void testActivityRecordProtoIsNotTooBig() {
// The ActivityRecordProto must not be too big, otherwise converting it at runtime
// will become prohibitively expensive.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 83cadf3..610edc0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1507,7 +1507,7 @@
final ActivityRecord activity = createActivityWithTask();
final WindowProcessController wpc = activity.app;
assertTrue(wpc.registeredForActivityConfigChanges());
- assertFalse(wpc.registeredForDisplayConfigChanges());
+ assertFalse(wpc.registeredForDisplayAreaConfigChanges());
final ActivityRecord secondaryDisplayActivity =
createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
@@ -1701,7 +1701,7 @@
assertTrue(wpc.registeredForActivityConfigChanges());
assertEquals(0, secondActivityRecord.getMergedOverrideConfiguration()
.diff(wpc.getRequestedOverrideConfiguration()));
- assertFalse(wpc.registeredForDisplayConfigChanges());
+ assertFalse(wpc.registeredForDisplayAreaConfigChanges());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index 99ec954..6f5a874 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -43,15 +43,11 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
@@ -60,7 +56,6 @@
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowManager;
-import android.window.IDisplayAreaOrganizer;
import com.google.android.collect.Lists;
@@ -503,42 +498,6 @@
assertThat(mDisplayContent.getOrientationRequestingTaskDisplayArea()).isEqualTo(tda);
}
- @Test
- public void onParentChanged_onDisplayAreaAppeared() {
- final DisplayArea<WindowContainer> displayArea = new DisplayArea<>(
- mWm, BELOW_TASKS, "NewArea", FEATURE_DEFAULT_TASK_CONTAINER);
-
- final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class);
- spyOn(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController);
- when(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController
- .getOrganizerByFeature(FEATURE_DEFAULT_TASK_CONTAINER))
- .thenReturn(mockDisplayAreaOrganizer);
-
- mDisplayContent.addChild(displayArea, 0);
- assertEquals(mockDisplayAreaOrganizer, displayArea.mOrganizer);
- verify(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController)
- .onDisplayAreaAppeared(
- eq(mockDisplayAreaOrganizer),
- argThat(it -> it == displayArea && it.getSurfaceControl() != null));
- }
-
- @Test
- public void onParentChanged_onDisplayAreaVanished() {
- final DisplayArea<WindowContainer> displayArea = new DisplayArea<>(
- mWm, BELOW_TASKS, "NewArea", FEATURE_DEFAULT_TASK_CONTAINER);
-
- final IDisplayAreaOrganizer mockDisplayAreaOrganizer = mock(IDisplayAreaOrganizer.class);
- displayArea.mOrganizer = mockDisplayAreaOrganizer;
- spyOn(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController);
-
- mDisplayContent.addChild(displayArea, 0);
- displayArea.removeImmediately();
-
- assertNull(displayArea.mOrganizer);
- verify(mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController)
- .onDisplayAreaVanished(mockDisplayAreaOrganizer, displayArea);
- }
-
private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> {
private TestDisplayArea(WindowManagerService wms, Rect bounds) {
super(wms, ANY, "half display area");
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 69b8ccf..9527625 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -872,6 +872,16 @@
mDisplayContent.getImeTarget(IME_TARGET_LAYERING));
}
+ @UseTestDisplay(addWindows = W_INPUT_METHOD)
+ @Test
+ public void testInputMethodSet_listenOnDisplayAreaConfigurationChanged() {
+ spyOn(mAtm);
+ mDisplayContent.setInputMethodWindowLocked(mImeWindow);
+
+ verify(mAtm).onImeWindowSetOnDisplayArea(
+ mImeWindow.mSession.mPid, mDisplayContent.getImeContainer());
+ }
+
@Test
public void testAllowsTopmostFullscreenOrientation() {
final DisplayContent dc = createNewDisplay();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index e190248..22430a1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -20,8 +20,10 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
+import static android.view.SurfaceProto.ROTATION_180;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -39,7 +41,6 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.clearInvocations;
@@ -243,7 +244,7 @@
// The bounds should be [800, 0 - 1800, 2500].
assertEquals(origBounds.width(), currentBounds.width());
assertEquals(origBounds.height(), currentBounds.height());
- assertEquals(Configuration.ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
+ assertEquals(ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
// The previous resize operation doesn't consider the rotation change after size changed.
@@ -729,7 +730,7 @@
// Update with new activity requested orientation and recompute bounds with no previous
// size compat cache.
verify(mTask).onDescendantOrientationChanged(same(newActivity));
- verify(mTask).computeFullscreenBounds(any(), any(), any(), anyInt());
+ verify(mTask).computeFullscreenBounds(any(), any());
final Rect displayBounds = new Rect(display.getBounds());
final Rect taskBounds = new Rect(mTask.getBounds());
@@ -770,7 +771,7 @@
// Update with new activity requested orientation and recompute bounds with no previous
// size compat cache.
verify(mTask).onDescendantOrientationChanged(same(newActivity));
- verify(mTask).computeFullscreenBounds(any(), any(), any(), anyInt());
+ verify(mTask).computeFullscreenBounds(any(), any());
final Rect displayBounds = new Rect(display.getBounds());
final Rect taskBounds = new Rect(mTask.getBounds());
@@ -821,6 +822,88 @@
assertEquals(activityBounds, mActivity.getBounds());
}
+ @Test
+ public void testDisplayIgnoreOrientationRequest_rotated180_notInSizeCompat() {
+ // Set up a display in landscape and ignoring orientation request.
+ setUpDisplaySizeWithApp(2800, 1400);
+ final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ // Portrait fixed app.
+ prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
+
+ // In Task letterbox
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+
+ // Rotate display to portrait.
+ rotateDisplay(display, ROTATION_90);
+
+ // App should be in size compat.
+ assertFalse(mTask.isTaskLetterboxed());
+ assertScaled();
+
+ // Rotate display to landscape.
+ rotateDisplay(display, ROTATION_180);
+
+ // In Task letterbox
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+ }
+
+ @Test
+ public void testDisplayIgnoreOrientationRequestWithInsets_rotated180_notInSizeCompat() {
+ // Set up a display in portrait with display cutout and ignoring orientation request.
+ final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1400, 2800)
+ .setNotch(75)
+ .build();
+ setUpApp(display);
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ // Landscape fixed app.
+ prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);
+
+ // In Task letterbox
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+
+ // Rotate display to portrait.
+ rotateDisplay(display, ROTATION_90);
+
+ // App should be in size compat.
+ assertFalse(mTask.isTaskLetterboxed());
+ assertScaled();
+
+ // Rotate display to landscape.
+ rotateDisplay(display, ROTATION_180);
+
+ // In Task letterbox
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+ }
+
+ @Test
+ public void testTaskDisplayAreaNotFillDisplay() {
+ setUpDisplaySizeWithApp(1400, 2800);
+ final DisplayContent display = mActivity.mDisplayContent;
+ final TaskDisplayArea taskDisplayArea = mActivity.getDisplayArea();
+ taskDisplayArea.setBounds(0, 0, 1000, 2400);
+
+ // Portrait fixed app.
+ prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);
+
+ final Rect displayBounds = new Rect(display.getBounds());
+ assertEquals(ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
+ assertEquals(2800, displayBounds.width());
+ assertEquals(1400, displayBounds.height());
+ taskDisplayArea.setBounds(0, 0, 2400, 1000);
+
+ final Rect activityBounds = new Rect(mActivity.getBounds());
+ assertFalse(mActivity.inSizeCompatMode());
+ assertEquals(2400, activityBounds.width());
+ assertEquals(1000, activityBounds.height());
+ }
+
private static WindowState addWindowToActivity(ActivityRecord activity) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 3057558..f848ce5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -20,7 +20,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.Display.INVALID_DISPLAY;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -41,6 +40,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import org.junit.Before;
@@ -74,41 +74,69 @@
}
@Test
- public void testDisplayConfigurationListener() {
+ public void testDisplayAreaConfigurationListener() {
+ // By default, the process should not listen to any display area.
+ assertNull(mWpc.getDisplayArea());
- //By default, the process should not listen to any display.
- assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
+ // Register to ImeContainer on display 1 as a listener.
+ final TestDisplayContent testDisplayContent1 = createTestDisplayContentInContainer();
+ final DisplayArea imeContainer1 = testDisplayContent1.getImeContainer();
+ mWpc.registerDisplayAreaConfigurationListener(imeContainer1);
+ assertTrue(imeContainer1.containsListener(mWpc));
+ assertEquals(imeContainer1, mWpc.getDisplayArea());
- // Register to display 1 as a listener.
- TestDisplayContent testDisplayContent1 = createTestDisplayContentInContainer();
- mWpc.registerDisplayConfigurationListener(testDisplayContent1);
- assertTrue(testDisplayContent1.containsListener(mWpc));
- assertEquals(testDisplayContent1.mDisplayId, mWpc.getDisplayId());
+ // Register to ImeContainer on display 2 as a listener.
+ final TestDisplayContent testDisplayContent2 = createTestDisplayContentInContainer();
+ final DisplayArea imeContainer2 = testDisplayContent2.getImeContainer();
+ mWpc.registerDisplayAreaConfigurationListener(imeContainer2);
+ assertFalse(imeContainer1.containsListener(mWpc));
+ assertTrue(imeContainer2.containsListener(mWpc));
+ assertEquals(imeContainer2, mWpc.getDisplayArea());
- // Move to display 2.
- TestDisplayContent testDisplayContent2 = createTestDisplayContentInContainer();
- mWpc.registerDisplayConfigurationListener(testDisplayContent2);
- assertFalse(testDisplayContent1.containsListener(mWpc));
- assertTrue(testDisplayContent2.containsListener(mWpc));
- assertEquals(testDisplayContent2.mDisplayId, mWpc.getDisplayId());
+ // Null DisplayArea will not change anything.
+ mWpc.registerDisplayAreaConfigurationListener(null);
+ assertTrue(imeContainer2.containsListener(mWpc));
+ assertEquals(imeContainer2, mWpc.getDisplayArea());
- // Null DisplayContent will not change anything.
- mWpc.registerDisplayConfigurationListener(null);
- assertTrue(testDisplayContent2.containsListener(mWpc));
- assertEquals(testDisplayContent2.mDisplayId, mWpc.getDisplayId());
-
- // Unregister listener will remove the wpc from registered displays.
- mWpc.unregisterDisplayConfigurationListener();
- assertFalse(testDisplayContent1.containsListener(mWpc));
- assertFalse(testDisplayContent2.containsListener(mWpc));
- assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
+ // Unregister listener will remove the wpc from registered display area.
+ mWpc.unregisterDisplayAreaConfigurationListener();
+ assertFalse(imeContainer1.containsListener(mWpc));
+ assertFalse(imeContainer2.containsListener(mWpc));
+ assertNull(mWpc.getDisplayArea());
// Unregistration still work even if the display was removed.
- mWpc.registerDisplayConfigurationListener(testDisplayContent1);
- assertEquals(testDisplayContent1.mDisplayId, mWpc.getDisplayId());
+ mWpc.registerDisplayAreaConfigurationListener(imeContainer1);
+ assertEquals(imeContainer1, mWpc.getDisplayArea());
mRootWindowContainer.removeChild(testDisplayContent1);
- mWpc.unregisterDisplayConfigurationListener();
- assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
+ mWpc.unregisterDisplayAreaConfigurationListener();
+ assertNull(mWpc.getDisplayArea());
+ }
+
+ @Test
+ public void testDisplayAreaConfigurationListener_verifyConfig() {
+ final Rect displayBounds = new Rect(0, 0, 2000, 1000);
+ final DisplayContent display = new TestDisplayContent.Builder(
+ mAtm, displayBounds.width(), displayBounds.height())
+ .setDensityDpi(300)
+ .setPosition(DisplayContent.POSITION_TOP)
+ .build();
+ final DisplayArea imeContainer = display.getImeContainer();
+
+ // Register to the ime container.
+ mWpc.registerDisplayAreaConfigurationListener(imeContainer);
+
+ assertEquals(displayBounds, mWpc.getConfiguration().windowConfiguration.getBounds());
+
+ // Resize the ime container.
+ final Rect resizeImeBounds = new Rect(0, 0, 1000, 1000);
+ imeContainer.setBounds(resizeImeBounds);
+
+ assertEquals(resizeImeBounds, mWpc.getConfiguration().windowConfiguration.getBounds());
+
+ // Register to the display.
+ mWpc.registerDisplayAreaConfigurationListener(display);
+
+ assertEquals(displayBounds, mWpc.getConfiguration().windowConfiguration.getBounds());
}
@Test
@@ -149,18 +177,19 @@
}
@Test
- public void testConfigurationForSecondaryScreen() {
- // By default, the process should not listen to any display.
- assertEquals(INVALID_DISPLAY, mWpc.getDisplayId());
+ public void testConfigurationForSecondaryScreenDisplayArea() {
+ // By default, the process should not listen to any display area.
+ assertNull(mWpc.getDisplayArea());
- // Register to a new display as a listener.
+ // Register to the ImeContainer on the new display as a listener.
final DisplayContent display = new TestDisplayContent.Builder(mAtm, 2000, 1000)
.setDensityDpi(300).setPosition(DisplayContent.POSITION_TOP).build();
- mWpc.registerDisplayConfigurationListener(display);
+ final DisplayArea imeContainer = display.getImeContainer();
+ mWpc.registerDisplayAreaConfigurationListener(imeContainer);
- assertEquals(display.mDisplayId, mWpc.getDisplayId());
+ assertEquals(imeContainer, mWpc.getDisplayArea());
final Configuration expectedConfig = mAtm.mRootWindowContainer.getConfiguration();
- expectedConfig.updateFrom(display.getConfiguration());
+ expectedConfig.updateFrom(imeContainer.getConfiguration());
assertEquals(expectedConfig, mWpc.getConfiguration());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 7db2fc9..263aa19 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -448,6 +448,26 @@
}
@Test
+ public void testDeferredRemovalByAnimating() {
+ final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
+ makeWindowVisible(appWindow);
+ spyOn(appWindow.mWinAnimator);
+ doReturn(true).when(appWindow.mWinAnimator).getShown();
+ final AnimationAdapter animation = mock(AnimationAdapter.class);
+ final ActivityRecord activity = appWindow.mActivityRecord;
+ activity.startAnimation(appWindow.getPendingTransaction(),
+ animation, false /* hidden */, SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION);
+
+ appWindow.removeIfPossible();
+ assertTrue(appWindow.mAnimatingExit);
+ assertFalse(appWindow.mRemoved);
+
+ activity.cancelAnimation();
+ assertFalse(appWindow.mAnimatingExit);
+ assertTrue(appWindow.mRemoved);
+ }
+
+ @Test
public void testLayoutSeqResetOnReparent() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
app.mLayoutSeq = 1;
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index fd462c2..bfb159f 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -54,6 +54,7 @@
import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
+import java.util.Arrays;
import java.util.List;
public class IntervalStats {
@@ -459,13 +460,14 @@
*/
private boolean deobfuscateUsageStats(PackagesTokenData packagesTokenData) {
boolean dataOmitted = false;
+ final ArraySet<Integer> omittedTokens = new ArraySet<>();
final int usageStatsSize = packageStatsObfuscated.size();
for (int statsIndex = 0; statsIndex < usageStatsSize; statsIndex++) {
final int packageToken = packageStatsObfuscated.keyAt(statsIndex);
final UsageStats usageStats = packageStatsObfuscated.valueAt(statsIndex);
usageStats.mPackageName = packagesTokenData.getPackageString(packageToken);
if (usageStats.mPackageName == null) {
- Slog.e(TAG, "Unable to parse usage stats package " + packageToken);
+ omittedTokens.add(packageToken);
dataOmitted = true;
continue;
}
@@ -477,8 +479,6 @@
final int actionToken = usageStats.mChooserCountsObfuscated.keyAt(actionIndex);
final String action = packagesTokenData.getString(packageToken, actionToken);
if (action == null) {
- Slog.i(TAG, "Unable to parse chooser action " + actionToken
- + " for package " + packageToken);
continue;
}
final SparseIntArray categoryCounts =
@@ -489,8 +489,6 @@
final String category = packagesTokenData.getString(packageToken,
categoryToken);
if (category == null) {
- Slog.i(TAG, "Unable to parse chooser category " + categoryToken
- + " for package " + packageToken);
continue;
}
categoryCountsMap.put(category, categoryCounts.valueAt(categoryIndex));
@@ -499,6 +497,10 @@
}
packageStats.put(usageStats.mPackageName, usageStats);
}
+ if (dataOmitted) {
+ Slog.d(TAG, "Unable to parse usage stats packages: "
+ + Arrays.toString(omittedTokens.toArray()));
+ }
return dataOmitted;
}
@@ -511,12 +513,13 @@
*/
private boolean deobfuscateEvents(PackagesTokenData packagesTokenData) {
boolean dataOmitted = false;
+ final ArraySet<Integer> omittedTokens = new ArraySet<>();
for (int i = this.events.size() - 1; i >= 0; i--) {
final Event event = this.events.get(i);
final int packageToken = event.mPackageToken;
event.mPackage = packagesTokenData.getPackageString(packageToken);
if (event.mPackage == null) {
- Slog.e(TAG, "Unable to parse event package " + packageToken);
+ omittedTokens.add(packageToken);
this.events.remove(i);
dataOmitted = true;
continue;
@@ -524,26 +527,14 @@
if (event.mClassToken != PackagesTokenData.UNASSIGNED_TOKEN) {
event.mClass = packagesTokenData.getString(packageToken, event.mClassToken);
- if (event.mClass == null) {
- Slog.i(TAG, "Unable to parse class " + event.mClassToken
- + " for package " + packageToken);
- }
}
if (event.mTaskRootPackageToken != PackagesTokenData.UNASSIGNED_TOKEN) {
event.mTaskRootPackage = packagesTokenData.getString(packageToken,
event.mTaskRootPackageToken);
- if (event.mTaskRootPackage == null) {
- Slog.i(TAG, "Unable to parse task root package " + event.mTaskRootPackageToken
- + " for package " + packageToken);
- }
}
if (event.mTaskRootClassToken != PackagesTokenData.UNASSIGNED_TOKEN) {
event.mTaskRootClass = packagesTokenData.getString(packageToken,
event.mTaskRootClassToken);
- if (event.mTaskRootClass == null) {
- Slog.i(TAG, "Unable to parse task root class " + event.mTaskRootClassToken
- + " for package " + packageToken);
- }
}
switch (event.mEventType) {
case CONFIGURATION_CHANGE:
@@ -555,7 +546,7 @@
event.mShortcutId = packagesTokenData.getString(packageToken,
event.mShortcutIdToken);
if (event.mShortcutId == null) {
- Slog.e(TAG, "Unable to parse shortcut " + event.mShortcutIdToken
+ Slog.v(TAG, "Unable to parse shortcut " + event.mShortcutIdToken
+ " for package " + packageToken);
this.events.remove(i);
dataOmitted = true;
@@ -566,7 +557,7 @@
event.mNotificationChannelId = packagesTokenData.getString(packageToken,
event.mNotificationChannelIdToken);
if (event.mNotificationChannelId == null) {
- Slog.e(TAG, "Unable to parse notification channel "
+ Slog.v(TAG, "Unable to parse notification channel "
+ event.mNotificationChannelIdToken + " for package "
+ packageToken);
this.events.remove(i);
@@ -577,7 +568,7 @@
case LOCUS_ID_SET:
event.mLocusId = packagesTokenData.getString(packageToken, event.mLocusIdToken);
if (event.mLocusId == null) {
- Slog.e(TAG, "Unable to parse locus " + event.mLocusIdToken
+ Slog.v(TAG, "Unable to parse locus " + event.mLocusIdToken
+ " for package " + packageToken);
this.events.remove(i);
dataOmitted = true;
@@ -586,6 +577,10 @@
break;
}
}
+ if (dataOmitted) {
+ Slog.d(TAG, "Unable to parse event packages: "
+ + Arrays.toString(omittedTokens.toArray()));
+ }
return dataOmitted;
}
diff --git a/services/usage/java/com/android/server/usage/PackagesTokenData.java b/services/usage/java/com/android/server/usage/PackagesTokenData.java
index f19abbb..272daf4 100644
--- a/services/usage/java/com/android/server/usage/PackagesTokenData.java
+++ b/services/usage/java/com/android/server/usage/PackagesTokenData.java
@@ -16,6 +16,7 @@
package com.android.server.usage;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
@@ -56,6 +57,11 @@
* Stores a map of packages that were removed and when they were removed.
*/
public final ArrayMap<String, Long> removedPackagesMap = new ArrayMap<>();
+ /**
+ * Stores a set of removed package tokens. This is solely for dump purposes when comparing
+ * parsing errors to recently removed packages.
+ */
+ public final ArraySet<Integer> removedPackageTokens = new ArraySet<>();
public PackagesTokenData() {
}
@@ -174,6 +180,7 @@
final int packageToken = packagesToTokensMap.get(packageName).get(packageName);
packagesToTokensMap.remove(packageName);
tokensToPackagesMap.delete(packageToken);
+ removedPackageTokens.add(packageToken);
return packageToken;
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 9d48955..a4f5249 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -53,6 +53,7 @@
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -1500,6 +1501,10 @@
pw.increaseIndent();
pw.println("Counter: " + mPackagesTokenData.counter);
pw.println("Tokens Map Size: " + mPackagesTokenData.tokensToPackagesMap.size());
+ if (!mPackagesTokenData.removedPackageTokens.isEmpty()) {
+ pw.println("Removed Package Tokens: "
+ + Arrays.toString(mPackagesTokenData.removedPackageTokens.toArray()));
+ }
for (int i = 0; i < mPackagesTokenData.tokensToPackagesMap.size(); i++) {
final int packageToken = mPackagesTokenData.tokensToPackagesMap.keyAt(i);
final String packageStrings = String.join(", ",
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 7a21b3a..04b365f 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -109,6 +109,20 @@
*/
public abstract class Connection extends Conferenceable {
+ /**@hide*/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "STATE_", value = {
+ STATE_INITIALIZING,
+ STATE_NEW,
+ STATE_RINGING,
+ STATE_DIALING,
+ STATE_ACTIVE,
+ STATE_HOLDING,
+ STATE_DISCONNECTED,
+ STATE_PULLING_CALL
+ })
+ public @interface ConnectionState {}
+
/**
* The connection is initializing. This is generally the first state for a {@code Connection}
* returned by a {@link ConnectionService}.
@@ -3285,7 +3299,7 @@
* Intent intent = new Intent(Intent.ACTION_MAIN, null);
* intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
* intent.setClass(context, YourIncomingCallActivity.class);
- * PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);
+ * PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
*
* // Build the notification as an ongoing high priority item; this ensures it will show as
* // a heads up notification which slides down over top of the current content.
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index 07de617..5cf8de8 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -179,7 +179,7 @@
* Intent intent = new Intent(Intent.ACTION_MAIN, null);
* intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
* intent.setClass(context, YourIncomingCallActivity.class);
- * PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);
+ * PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
*
* // Build the notification as an ongoing high priority item; this ensures it will show as
* // a heads up notification which slides down over top of the current content.
diff --git a/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java b/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java
new file mode 100644
index 0000000..c7e7cd5
--- /dev/null
+++ b/telephony/common/com/android/internal/telephony/SipMessageParsingUtils.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+import android.net.Uri;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Utility methods for parsing parts of {@link android.telephony.ims.SipMessage}s.
+ * See RFC 3261 for more information.
+ * @hide
+ */
+// Note: This is lightweight in order to avoid a full SIP stack import in frameworks/base.
+public class SipMessageParsingUtils {
+ private static final String TAG = "SipMessageParsingUtils";
+ // "Method" in request-line
+ // Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ private static final String[] SIP_REQUEST_METHODS = new String[] {"INVITE", "ACK", "OPTIONS",
+ "BYE", "CANCEL", "REGISTER", "PRACK", "SUBSCRIBE", "NOTIFY", "PUBLISH", "INFO", "REFER",
+ "MESSAGE", "UPDATE"};
+
+ // SIP Version 2.0 (corresponding to RCS 3261), set in "SIP-Version" of Status-Line and
+ // Request-Line
+ //
+ // Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
+ private static final String SIP_VERSION_2 = "SIP/2.0";
+
+ // headers are formatted Key:Value
+ private static final String HEADER_KEY_VALUE_SEPARATOR = ":";
+ // Multiple of the same header can be concatenated and put into one header Key:Value pair, for
+ // example "v: XX1;branch=YY1,XX2;branch=YY2". This needs to be treated as two "v:" headers.
+ private static final String SUBHEADER_VALUE_SEPARATOR = ",";
+
+ // SIP header parameters have the format ";paramName=paramValue"
+ private static final String PARAM_SEPARATOR = ";";
+ // parameters are formatted paramName=ParamValue
+ private static final String PARAM_KEY_VALUE_SEPARATOR = "=";
+
+ // The via branch parameter definition
+ private static final String BRANCH_PARAM_KEY = "branch";
+
+ // via header key
+ private static final String VIA_SIP_HEADER_KEY = "via";
+ // compact form of the via header key
+ private static final String VIA_SIP_HEADER_KEY_COMPACT = "v";
+
+ /**
+ * @return true if the SIP message start line is considered a request (based on known request
+ * methods).
+ */
+ public static boolean isSipRequest(String startLine) {
+ String[] splitLine = splitStartLineAndVerify(startLine);
+ if (splitLine == null) return false;
+ return verifySipRequest(splitLine);
+ }
+
+ /**
+ * Return the via branch parameter, which is used to identify the transaction ID (request and
+ * response pair) in a SIP transaction.
+ * @param headerString The string containing the headers of the SIP message.
+ */
+ public static String getTransactionId(String headerString) {
+ // search for Via: or v: parameter, we only care about the first one.
+ List<Pair<String, String>> headers = parseHeaders(headerString, true,
+ VIA_SIP_HEADER_KEY, VIA_SIP_HEADER_KEY_COMPACT);
+ for (Pair<String, String> header : headers) {
+ // Headers can also be concatenated together using a "," between each header value.
+ // format becomes v: XX1;branch=YY1,XX2;branch=YY2. Need to extract only the first ID's
+ // branch param YY1.
+ String[] subHeaders = header.second.split(SUBHEADER_VALUE_SEPARATOR);
+ for (String subHeader : subHeaders) {
+ // Search for ;branch=z9hG4bKXXXXXX and return parameter value
+ String[] params = subHeader.split(PARAM_SEPARATOR);
+ if (params.length < 2) {
+ // This param doesn't include a branch param, move to next param.
+ Log.w(TAG, "getTransactionId: via detected without branch param:"
+ + subHeader);
+ continue;
+ }
+ // by spec, each param can only appear once in a header.
+ for (String param : params) {
+ String[] pair = param.split(PARAM_KEY_VALUE_SEPARATOR);
+ if (pair.length < 2) {
+ // ignore info before the first parameter
+ continue;
+ }
+ if (pair.length > 2) {
+ Log.w(TAG,
+ "getTransactionId: unexpected parameter" + Arrays.toString(pair));
+ }
+ // Trim whitespace in parameter
+ pair[0] = pair[0].trim();
+ pair[1] = pair[1].trim();
+ if (BRANCH_PARAM_KEY.equalsIgnoreCase(pair[0])) {
+ // There can be multiple "Via" headers in the SIP message, however we want
+ // to return the first once found, as this corresponds with the transaction
+ // that is relevant here.
+ return pair[1];
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private static String[] splitStartLineAndVerify(String startLine) {
+ String[] splitLine = startLine.split(" ");
+ if (isStartLineMalformed(splitLine)) return null;
+ return splitLine;
+ }
+
+ private static boolean isStartLineMalformed(String[] startLine) {
+ if (startLine == null || startLine.length == 0) {
+ return true;
+ }
+ // start lines contain three segments separated by spaces (SP):
+ // Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
+ return (startLine.length != 3);
+ }
+
+ private static boolean verifySipRequest(String[] request) {
+ // Request-Line = Method SP Request-URI SP SIP-Version CRLF
+ boolean verified = request[2].contains(SIP_VERSION_2);
+ verified &= (Uri.parse(request[1]).getScheme() != null);
+ verified &= Arrays.stream(SIP_REQUEST_METHODS).anyMatch(s -> request[0].contains(s));
+ return verified;
+ }
+
+ private static boolean verifySipResponse(String[] response) {
+ // Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF
+ boolean verified = response[0].contains(SIP_VERSION_2);
+ int statusCode = Integer.parseInt(response[1]);
+ verified &= (statusCode >= 100 && statusCode < 700);
+ return verified;
+ }
+
+ /**
+ * Parse a String representation of the Header portion of the SIP Message and re-structure it
+ * into a List of key->value pairs representing each header in the order that they appeared in
+ * the message.
+ *
+ * @param headerString The raw string containing all headers
+ * @param stopAtFirstMatch Return early when the first match is found from matching header keys.
+ * @param matchingHeaderKeys An optional list of Strings containing header keys that should be
+ * returned if they exist. If none exist, all keys will be returned.
+ * (This is internally an equalsIgnoreMatch comparison).
+ * @return the matched header keys and values.
+ */
+ private static List<Pair<String, String>> parseHeaders(String headerString,
+ boolean stopAtFirstMatch, String... matchingHeaderKeys) {
+ // Ensure there is no leading whitespace
+ headerString = removeLeadingWhitespace(headerString);
+
+ List<Pair<String, String>> result = new ArrayList<>();
+ // Split the string line-by-line.
+ String[] headerLines = headerString.split("\\r?\\n");
+ if (headerLines.length == 0) {
+ return Collections.emptyList();
+ }
+
+ String headerKey = null;
+ StringBuilder headerValueSegment = new StringBuilder();
+ // loop through each line, either parsing a "key: value" pair or appending values that span
+ // multiple lines.
+ for (String line : headerLines) {
+ // This line is a continuation of the last line if it starts with whitespace or tab
+ if (line.startsWith("\t") || line.startsWith(" ")) {
+ headerValueSegment.append(removeLeadingWhitespace(line));
+ continue;
+ }
+ // This line is the start of a new key, If headerKey/value is already populated from a
+ // previous key/value pair, add it to list of parsed header pairs.
+ if (headerKey != null) {
+ final String key = headerKey;
+ if (matchingHeaderKeys == null || matchingHeaderKeys.length == 0
+ || Arrays.stream(matchingHeaderKeys).anyMatch(
+ (s) -> s.equalsIgnoreCase(key))) {
+ result.add(new Pair<>(key, headerValueSegment.toString()));
+ if (stopAtFirstMatch) {
+ return result;
+ }
+ }
+ headerKey = null;
+ headerValueSegment = new StringBuilder();
+ }
+
+ // Format is "Key:Value", ignore any ":" after the first.
+ String[] pair = line.split(HEADER_KEY_VALUE_SEPARATOR, 2);
+ if (pair.length < 2) {
+ // malformed line, skip
+ Log.w(TAG, "parseHeaders - received malformed line: " + line);
+ continue;
+ }
+
+ headerKey = pair[0].trim();
+ for (int i = 1; i < pair.length; i++) {
+ headerValueSegment.append(removeLeadingWhitespace(pair[i]));
+ }
+ }
+ // Pick up the last pending header being parsed, if it exists.
+ if (headerKey != null) {
+ final String key = headerKey;
+ if (matchingHeaderKeys == null || matchingHeaderKeys.length == 0
+ || Arrays.stream(matchingHeaderKeys).anyMatch(
+ (s) -> s.equalsIgnoreCase(key))) {
+ result.add(new Pair<>(key, headerValueSegment.toString()));
+ }
+ }
+
+ return result;
+ }
+
+ private static String removeLeadingWhitespace(String line) {
+ return line.replaceFirst("^\\s*", "");
+ }
+}
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index d012971..f6d18fc 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -18,10 +18,7 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
-import android.hardware.radio.V1_1.GeranBands;
import android.hardware.radio.V1_5.AccessNetwork;
-import android.hardware.radio.V1_5.EutranBands;
-import android.hardware.radio.V1_5.UtranBands;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -117,52 +114,120 @@
* http://www.etsi.org/deliver/etsi_ts/145000_145099/145005/14.00.00_60/ts_145005v140000p.pdf
*/
public static final class GeranBand {
- public static final int BAND_T380 = GeranBands.BAND_T380;
- public static final int BAND_T410 = GeranBands.BAND_T410;
- public static final int BAND_450 = GeranBands.BAND_450;
- public static final int BAND_480 = GeranBands.BAND_480;
- public static final int BAND_710 = GeranBands.BAND_710;
- public static final int BAND_750 = GeranBands.BAND_750;
- public static final int BAND_T810 = GeranBands.BAND_T810;
- public static final int BAND_850 = GeranBands.BAND_850;
- public static final int BAND_P900 = GeranBands.BAND_P900;
- public static final int BAND_E900 = GeranBands.BAND_E900;
- public static final int BAND_R900 = GeranBands.BAND_R900;
- public static final int BAND_DCS1800 = GeranBands.BAND_DCS1800;
- public static final int BAND_PCS1900 = GeranBands.BAND_PCS1900;
- public static final int BAND_ER900 = GeranBands.BAND_ER900;
+ public static final int BAND_T380 = android.hardware.radio.V1_1.GeranBands.BAND_T380;
+ public static final int BAND_T410 = android.hardware.radio.V1_1.GeranBands.BAND_T410;
+ public static final int BAND_450 = android.hardware.radio.V1_1.GeranBands.BAND_450;
+ public static final int BAND_480 = android.hardware.radio.V1_1.GeranBands.BAND_480;
+ public static final int BAND_710 = android.hardware.radio.V1_1.GeranBands.BAND_710;
+ public static final int BAND_750 = android.hardware.radio.V1_1.GeranBands.BAND_750;
+ public static final int BAND_T810 = android.hardware.radio.V1_1.GeranBands.BAND_T810;
+ public static final int BAND_850 = android.hardware.radio.V1_1.GeranBands.BAND_850;
+ public static final int BAND_P900 = android.hardware.radio.V1_1.GeranBands.BAND_P900;
+ public static final int BAND_E900 = android.hardware.radio.V1_1.GeranBands.BAND_E900;
+ public static final int BAND_R900 = android.hardware.radio.V1_1.GeranBands.BAND_R900;
+ public static final int BAND_DCS1800 = android.hardware.radio.V1_1.GeranBands.BAND_DCS1800;
+ public static final int BAND_PCS1900 = android.hardware.radio.V1_1.GeranBands.BAND_PCS1900;
+ public static final int BAND_ER900 = android.hardware.radio.V1_1.GeranBands.BAND_ER900;
+
+ /**
+ * GeranBand
+ *
+ * @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"BAND_"},
+ value = {BAND_T380,
+ BAND_T410,
+ BAND_450,
+ BAND_480,
+ BAND_710,
+ BAND_750,
+ BAND_T810,
+ BAND_850,
+ BAND_P900,
+ BAND_E900,
+ BAND_R900,
+ BAND_DCS1800,
+ BAND_PCS1900,
+ BAND_ER900})
+
+ public @interface GeranBands {}
/** @hide */
private GeranBand() {}
}
/**
+ * 3GPP TS 45.005 Table 2-1 Dynamically mapped ARFCN.
+ * 3GPP TS 45.005 Table 2-2 Fixed designation of ARFCN.
+ * @hide
+ */
+ enum GeranBandArfcnFrequency {
+
+ // Dynamically mapped ARFCN
+// GERAN_ARFCN_FREQUENCY_BAND_T380(GeranBand.BAND_T380, 380.2, 0),
+// GERAN_ARFCN_FREQUENCY_BAND_T410(GeranBand.BAND_T410, 410.2, 0),
+// GERAN_ARFCN_FREQUENCY_BAND_710(GeranBand.BAND_710, 698, 0),
+// GERAN_ARFCN_FREQUENCY_BAND_750(GeranBand.BAND_750, 747, 438, 30),
+// GERAN_ARFCN_FREQUENCY_BAND_T810(GeranBand.BAND_T810, 806, 350),
+ // Fixed designation of ARFCN
+ GERAN_ARFCN_FREQUENCY_BAND_450(GeranBand.BAND_450, 450600, 259, 259, 293, 10),
+ GERAN_ARFCN_FREQUENCY_BAND_480(GeranBand.BAND_480, 479000, 306, 306, 340, 10),
+ GERAN_ARFCN_FREQUENCY_BAND_850(GeranBand.BAND_850, 824200, 128, 128, 251, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_DCS1800(GeranBand.BAND_DCS1800, 1710200, 512, 512, 885, 95),
+ GERAN_ARFCN_FREQUENCY_BAND_PCS1900(GeranBand.BAND_PCS1900, 1850200, 512, 512, 810, 80),
+ GERAN_ARFCN_FREQUENCY_BAND_E900_1(GeranBand.BAND_E900, 890000, 0, 0, 124, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_E900_2(GeranBand.BAND_E900, 890000, 1024, 975, 1023, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_R900_1(GeranBand.BAND_R900, 890000, 0, 0, 124, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_R900_2(GeranBand.BAND_R900, 890000, 1024, 955, 1023, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_P900(GeranBand.BAND_P900, 890000, 0, 1, 124, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_ER900_1(GeranBand.BAND_ER900, 890000, 0, 0, 124, 45),
+ GERAN_ARFCN_FREQUENCY_BAND_ER900_2(GeranBand.BAND_ER900, 890000, 1024, 940, 1023, 1024);
+
+ GeranBandArfcnFrequency(int band, int uplinkFrequencyFirstKhz, int arfcnOffset,
+ int arfcnRangeFirst, int arfcnRangeLast, int downlinkOffset) {
+ this.band = band;
+ this.uplinkFrequencyFirst = uplinkFrequencyFirstKhz;
+ this.arfcnOffset = arfcnOffset;
+ this.arfcnRangeFirst = arfcnRangeFirst;
+ this.arfcnRangeLast = arfcnRangeLast;
+ this.downlinkOffset = downlinkOffset;
+ }
+
+ int band;
+ int uplinkFrequencyFirst;
+ int arfcnOffset;
+ int arfcnRangeFirst;
+ int arfcnRangeLast;
+ int downlinkOffset;
+ }
+
+ /**
* Frequency bands for UTRAN.
* http://www.etsi.org/deliver/etsi_ts/125100_125199/125104/13.03.00_60/ts_125104v130p.pdf
*/
public static final class UtranBand {
- public static final int BAND_1 = UtranBands.BAND_1;
- public static final int BAND_2 = UtranBands.BAND_2;
- public static final int BAND_3 = UtranBands.BAND_3;
- public static final int BAND_4 = UtranBands.BAND_4;
- public static final int BAND_5 = UtranBands.BAND_5;
- public static final int BAND_6 = UtranBands.BAND_6;
- public static final int BAND_7 = UtranBands.BAND_7;
- public static final int BAND_8 = UtranBands.BAND_8;
- public static final int BAND_9 = UtranBands.BAND_9;
- public static final int BAND_10 = UtranBands.BAND_10;
- public static final int BAND_11 = UtranBands.BAND_11;
- public static final int BAND_12 = UtranBands.BAND_12;
- public static final int BAND_13 = UtranBands.BAND_13;
- public static final int BAND_14 = UtranBands.BAND_14;
+ public static final int BAND_1 = android.hardware.radio.V1_5.UtranBands.BAND_1;
+ public static final int BAND_2 = android.hardware.radio.V1_5.UtranBands.BAND_2;
+ public static final int BAND_3 = android.hardware.radio.V1_5.UtranBands.BAND_3;
+ public static final int BAND_4 = android.hardware.radio.V1_5.UtranBands.BAND_4;
+ public static final int BAND_5 = android.hardware.radio.V1_5.UtranBands.BAND_5;
+ public static final int BAND_6 = android.hardware.radio.V1_5.UtranBands.BAND_6;
+ public static final int BAND_7 = android.hardware.radio.V1_5.UtranBands.BAND_7;
+ public static final int BAND_8 = android.hardware.radio.V1_5.UtranBands.BAND_8;
+ public static final int BAND_9 = android.hardware.radio.V1_5.UtranBands.BAND_9;
+ public static final int BAND_10 = android.hardware.radio.V1_5.UtranBands.BAND_10;
+ public static final int BAND_11 = android.hardware.radio.V1_5.UtranBands.BAND_11;
+ public static final int BAND_12 = android.hardware.radio.V1_5.UtranBands.BAND_12;
+ public static final int BAND_13 = android.hardware.radio.V1_5.UtranBands.BAND_13;
+ public static final int BAND_14 = android.hardware.radio.V1_5.UtranBands.BAND_14;
// band 15, 16, 17, 18 are reserved
- public static final int BAND_19 = UtranBands.BAND_19;
- public static final int BAND_20 = UtranBands.BAND_20;
- public static final int BAND_21 = UtranBands.BAND_21;
- public static final int BAND_22 = UtranBands.BAND_22;
+ public static final int BAND_19 = android.hardware.radio.V1_5.UtranBands.BAND_19;
+ public static final int BAND_20 = android.hardware.radio.V1_5.UtranBands.BAND_20;
+ public static final int BAND_21 = android.hardware.radio.V1_5.UtranBands.BAND_21;
+ public static final int BAND_22 = android.hardware.radio.V1_5.UtranBands.BAND_22;
// band 23, 24 are reserved
- public static final int BAND_25 = UtranBands.BAND_25;
- public static final int BAND_26 = UtranBands.BAND_26;
+ public static final int BAND_25 = android.hardware.radio.V1_5.UtranBands.BAND_25;
+ public static final int BAND_26 = android.hardware.radio.V1_5.UtranBands.BAND_26;
// Frequency bands for TD-SCDMA. Defined in 3GPP TS 25.102, Table 5.2.
@@ -171,115 +236,423 @@
* 1900 - 1920 MHz: Uplink and downlink transmission
* 2010 - 2025 MHz: Uplink and downlink transmission
*/
- public static final int BAND_A = UtranBands.BAND_A;
+ public static final int BAND_A = android.hardware.radio.V1_5.UtranBands.BAND_A;
/**
* Band B
* 1850 - 1910 MHz: Uplink and downlink transmission
* 1930 - 1990 MHz: Uplink and downlink transmission
*/
- public static final int BAND_B = UtranBands.BAND_B;
+ public static final int BAND_B = android.hardware.radio.V1_5.UtranBands.BAND_B;
/**
* Band C
* 1910 - 1930 MHz: Uplink and downlink transmission
*/
- public static final int BAND_C = UtranBands.BAND_C;
+ public static final int BAND_C = android.hardware.radio.V1_5.UtranBands.BAND_C;
/**
* Band D
* 2570 - 2620 MHz: Uplink and downlink transmission
*/
- public static final int BAND_D = UtranBands.BAND_D;
+ public static final int BAND_D = android.hardware.radio.V1_5.UtranBands.BAND_D;
/**
* Band E
* 2300—2400 MHz: Uplink and downlink transmission
*/
- public static final int BAND_E = UtranBands.BAND_E;
+ public static final int BAND_E = android.hardware.radio.V1_5.UtranBands.BAND_E;
/**
* Band F
* 1880 - 1920 MHz: Uplink and downlink transmission
*/
- public static final int BAND_F = UtranBands.BAND_F;
+ public static final int BAND_F = android.hardware.radio.V1_5.UtranBands.BAND_F;
+
+ /**
+ * UtranBand
+ *
+ * @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"BAND_"},
+ value = {BAND_1,
+ BAND_2,
+ BAND_3,
+ BAND_4,
+ BAND_5,
+ BAND_6,
+ BAND_7,
+ BAND_8,
+ BAND_9,
+ BAND_10,
+ BAND_11,
+ BAND_12,
+ BAND_13,
+ BAND_14,
+ BAND_19,
+ BAND_20,
+ BAND_21,
+ BAND_22,
+ BAND_25,
+ BAND_26,
+ BAND_A,
+ BAND_B,
+ BAND_C,
+ BAND_D,
+ BAND_E,
+ BAND_F})
+
+ public @interface UtranBands {}
/** @hide */
private UtranBand() {}
}
/**
+ * 3GPP TS 25.101, Table 5.1 UARFCN definition (general)
+ * 3GPP TS 25.102, Table 5.2 UTRA Absolute Radio Frequency Channel Number 1.28 Mcps TDD Option.
+ *
+ * @hide
+ */
+ enum UtranBandArfcnFrequency {
+
+ UTRAN_ARFCN_FREQUENCY_BAND_1(UtranBand.BAND_1, 0, 10562, 10838, 0, 9612, 9888),
+ UTRAN_ARFCN_FREQUENCY_BAND_2(UtranBand.BAND_2, 0, 9662, 9938, 0, 9262, 9538),
+ UTRAN_ARFCN_FREQUENCY_BAND_3(UtranBand.BAND_3, 1575000, 1162, 1513, 1525000, 937, 1288),
+ UTRAN_ARFCN_FREQUENCY_BAND_4(UtranBand.BAND_4, 1805000, 1537, 1738, 1450000, 1312, 1513),
+ UTRAN_ARFCN_FREQUENCY_BAND_5(UtranBand.BAND_5, 0, 4357, 4458, 0, 4132, 4233),
+ UTRAN_ARFCN_FREQUENCY_BAND_6(UtranBand.BAND_6, 0, 4387, 4413, 0, 4162, 4188),
+ UTRAN_ARFCN_FREQUENCY_BAND_7(UtranBand.BAND_7, 2175000, 2237, 2563, 2100000, 2012, 2338),
+ UTRAN_ARFCN_FREQUENCY_BAND_8(UtranBand.BAND_8, 340000, 2937, 3088, 340000, 2712, 2863),
+ UTRAN_ARFCN_FREQUENCY_BAND_9(UtranBand.BAND_9, 0, 9327, 9837, 0, 8762, 8912),
+ UTRAN_ARFCN_FREQUENCY_BAND_10(UtranBand.BAND_10, 1490000, 3112, 3388, 1135000, 2887, 3163),
+ UTRAN_ARFCN_FREQUENCY_BAND_11(UtranBand.BAND_11, 736000, 3712, 3787, 733000, 3487, 3562),
+ UTRAN_ARFCN_FREQUENCY_BAND_12(UtranBand.BAND_12, -37000, 3842, 3903, -22000, 3617, 3678),
+ UTRAN_ARFCN_FREQUENCY_BAND_13(UtranBand.BAND_13, -55000, 4017, 4043, 21000, 3792, 3818),
+ UTRAN_ARFCN_FREQUENCY_BAND_14(UtranBand.BAND_14, -63000, 4117, 4143, 12000, 3892, 3918),
+ UTRAN_ARFCN_FREQUENCY_BAND_19(UtranBand.BAND_19, 735000, 712, 763, 770000, 312, 363),
+ UTRAN_ARFCN_FREQUENCY_BAND_20(UtranBand.BAND_20, -109000, 4512, 4638, -23000, 4287, 4413),
+ UTRAN_ARFCN_FREQUENCY_BAND_21(UtranBand.BAND_21, 1326000, 862, 912, 1358000, 462, 512),
+ UTRAN_ARFCN_FREQUENCY_BAND_22(UtranBand.BAND_22, 2580000, 4662, 5038, 2525000, 4437, 4813),
+ UTRAN_ARFCN_FREQUENCY_BAND_25(UtranBand.BAND_25, 910000, 5112, 5413, 875000, 4887, 5188),
+ UTRAN_ARFCN_FREQUENCY_BAND_A(UtranBand.BAND_A, 0, 10054, 10121, 0, 9504, 9596),
+ UTRAN_ARFCN_FREQUENCY_BAND_B(UtranBand.BAND_B, 0, 9654, 9946, 0, 9254, 9546),
+ UTRAN_ARFCN_FREQUENCY_BAND_C(UtranBand.BAND_C, 0, 0, 0, 0, 9554, 9646),
+ UTRAN_ARFCN_FREQUENCY_BAND_D(UtranBand.BAND_D, 0, 0, 0, 0, 12854, 13096),
+ UTRAN_ARFCN_FREQUENCY_BAND_E(UtranBand.BAND_E, 0, 0, 0, 0, 11504, 11996),
+ UTRAN_ARFCN_FREQUENCY_BAND_F(UtranBand.BAND_F, 0, 0, 0, 0, 9404, 9596);
+
+ UtranBandArfcnFrequency(int band, int downlinkOffsetKhz, int downlinkRangeFirst,
+ int downlinkRangeLast, int uplinkOffsetKhz, int uplinkRangeFirst,
+ int uplinkRangeLast) {
+ this.band = band;
+ this.downlinkOffset = downlinkOffsetKhz;
+ this.downlinkRangeFirst = downlinkRangeFirst;
+ this.downlinkRangeLast = downlinkRangeLast;
+ this.uplinkOffset = uplinkOffsetKhz;
+ this.uplinkRangeFirst = uplinkRangeFirst;
+ this.uplinkRangeLast = uplinkRangeLast;
+ }
+
+ int band;
+ int downlinkOffset;
+ int downlinkRangeFirst;
+ int downlinkRangeLast;
+ int uplinkOffset;
+ int uplinkRangeFirst;
+ int uplinkRangeLast;
+ }
+
+ /**
* Frequency bands for EUTRAN.
* 3GPP TS 36.101, Version 16.4.0, Table 5.5: Operating bands
* https://www.etsi.org/deliver/etsi_ts/136100_136199/136101/15.09.00_60/ts_136101v150900p.pdf
*/
public static final class EutranBand {
- public static final int BAND_1 = EutranBands.BAND_1;
- public static final int BAND_2 = EutranBands.BAND_2;
- public static final int BAND_3 = EutranBands.BAND_3;
- public static final int BAND_4 = EutranBands.BAND_4;
- public static final int BAND_5 = EutranBands.BAND_5;
- public static final int BAND_6 = EutranBands.BAND_6;
- public static final int BAND_7 = EutranBands.BAND_7;
- public static final int BAND_8 = EutranBands.BAND_8;
- public static final int BAND_9 = EutranBands.BAND_9;
- public static final int BAND_10 = EutranBands.BAND_10;
- public static final int BAND_11 = EutranBands.BAND_11;
- public static final int BAND_12 = EutranBands.BAND_12;
- public static final int BAND_13 = EutranBands.BAND_13;
- public static final int BAND_14 = EutranBands.BAND_14;
- public static final int BAND_17 = EutranBands.BAND_17;
- public static final int BAND_18 = EutranBands.BAND_18;
- public static final int BAND_19 = EutranBands.BAND_19;
- public static final int BAND_20 = EutranBands.BAND_20;
- public static final int BAND_21 = EutranBands.BAND_21;
- public static final int BAND_22 = EutranBands.BAND_22;
- public static final int BAND_23 = EutranBands.BAND_23;
- public static final int BAND_24 = EutranBands.BAND_24;
- public static final int BAND_25 = EutranBands.BAND_25;
- public static final int BAND_26 = EutranBands.BAND_26;
- public static final int BAND_27 = EutranBands.BAND_27;
- public static final int BAND_28 = EutranBands.BAND_28;
- public static final int BAND_30 = EutranBands.BAND_30;
- public static final int BAND_31 = EutranBands.BAND_31;
- public static final int BAND_33 = EutranBands.BAND_33;
- public static final int BAND_34 = EutranBands.BAND_34;
- public static final int BAND_35 = EutranBands.BAND_35;
- public static final int BAND_36 = EutranBands.BAND_36;
- public static final int BAND_37 = EutranBands.BAND_37;
- public static final int BAND_38 = EutranBands.BAND_38;
- public static final int BAND_39 = EutranBands.BAND_39;
- public static final int BAND_40 = EutranBands.BAND_40;
- public static final int BAND_41 = EutranBands.BAND_41;
- public static final int BAND_42 = EutranBands.BAND_42;
- public static final int BAND_43 = EutranBands.BAND_43;
- public static final int BAND_44 = EutranBands.BAND_44;
- public static final int BAND_45 = EutranBands.BAND_45;
- public static final int BAND_46 = EutranBands.BAND_46;
- public static final int BAND_47 = EutranBands.BAND_47;
- public static final int BAND_48 = EutranBands.BAND_48;
- public static final int BAND_49 = EutranBands.BAND_49;
- public static final int BAND_50 = EutranBands.BAND_50;
- public static final int BAND_51 = EutranBands.BAND_51;
- public static final int BAND_52 = EutranBands.BAND_52;
- public static final int BAND_53 = EutranBands.BAND_53;
- public static final int BAND_65 = EutranBands.BAND_65;
- public static final int BAND_66 = EutranBands.BAND_66;
- public static final int BAND_68 = EutranBands.BAND_68;
- public static final int BAND_70 = EutranBands.BAND_70;
- public static final int BAND_71 = EutranBands.BAND_71;
- public static final int BAND_72 = EutranBands.BAND_72;
- public static final int BAND_73 = EutranBands.BAND_73;
- public static final int BAND_74 = EutranBands.BAND_74;
- public static final int BAND_85 = EutranBands.BAND_85;
- public static final int BAND_87 = EutranBands.BAND_87;
- public static final int BAND_88 = EutranBands.BAND_88;
+ public static final int BAND_1 = android.hardware.radio.V1_5.EutranBands.BAND_1;
+ public static final int BAND_2 = android.hardware.radio.V1_5.EutranBands.BAND_2;
+ public static final int BAND_3 = android.hardware.radio.V1_5.EutranBands.BAND_3;
+ public static final int BAND_4 = android.hardware.radio.V1_5.EutranBands.BAND_4;
+ public static final int BAND_5 = android.hardware.radio.V1_5.EutranBands.BAND_5;
+ public static final int BAND_6 = android.hardware.radio.V1_5.EutranBands.BAND_6;
+ public static final int BAND_7 = android.hardware.radio.V1_5.EutranBands.BAND_7;
+ public static final int BAND_8 = android.hardware.radio.V1_5.EutranBands.BAND_8;
+ public static final int BAND_9 = android.hardware.radio.V1_5.EutranBands.BAND_9;
+ public static final int BAND_10 = android.hardware.radio.V1_5.EutranBands.BAND_10;
+ public static final int BAND_11 = android.hardware.radio.V1_5.EutranBands.BAND_11;
+ public static final int BAND_12 = android.hardware.radio.V1_5.EutranBands.BAND_12;
+ public static final int BAND_13 = android.hardware.radio.V1_5.EutranBands.BAND_13;
+ public static final int BAND_14 = android.hardware.radio.V1_5.EutranBands.BAND_14;
+ public static final int BAND_17 = android.hardware.radio.V1_5.EutranBands.BAND_17;
+ public static final int BAND_18 = android.hardware.radio.V1_5.EutranBands.BAND_18;
+ public static final int BAND_19 = android.hardware.radio.V1_5.EutranBands.BAND_19;
+ public static final int BAND_20 = android.hardware.radio.V1_5.EutranBands.BAND_20;
+ public static final int BAND_21 = android.hardware.radio.V1_5.EutranBands.BAND_21;
+ public static final int BAND_22 = android.hardware.radio.V1_5.EutranBands.BAND_22;
+ public static final int BAND_23 = android.hardware.radio.V1_5.EutranBands.BAND_23;
+ public static final int BAND_24 = android.hardware.radio.V1_5.EutranBands.BAND_24;
+ public static final int BAND_25 = android.hardware.radio.V1_5.EutranBands.BAND_25;
+ public static final int BAND_26 = android.hardware.radio.V1_5.EutranBands.BAND_26;
+ public static final int BAND_27 = android.hardware.radio.V1_5.EutranBands.BAND_27;
+ public static final int BAND_28 = android.hardware.radio.V1_5.EutranBands.BAND_28;
+ public static final int BAND_30 = android.hardware.radio.V1_5.EutranBands.BAND_30;
+ public static final int BAND_31 = android.hardware.radio.V1_5.EutranBands.BAND_31;
+ public static final int BAND_33 = android.hardware.radio.V1_5.EutranBands.BAND_33;
+ public static final int BAND_34 = android.hardware.radio.V1_5.EutranBands.BAND_34;
+ public static final int BAND_35 = android.hardware.radio.V1_5.EutranBands.BAND_35;
+ public static final int BAND_36 = android.hardware.radio.V1_5.EutranBands.BAND_36;
+ public static final int BAND_37 = android.hardware.radio.V1_5.EutranBands.BAND_37;
+ public static final int BAND_38 = android.hardware.radio.V1_5.EutranBands.BAND_38;
+ public static final int BAND_39 = android.hardware.radio.V1_5.EutranBands.BAND_39;
+ public static final int BAND_40 = android.hardware.radio.V1_5.EutranBands.BAND_40;
+ public static final int BAND_41 = android.hardware.radio.V1_5.EutranBands.BAND_41;
+ public static final int BAND_42 = android.hardware.radio.V1_5.EutranBands.BAND_42;
+ public static final int BAND_43 = android.hardware.radio.V1_5.EutranBands.BAND_43;
+ public static final int BAND_44 = android.hardware.radio.V1_5.EutranBands.BAND_44;
+ public static final int BAND_45 = android.hardware.radio.V1_5.EutranBands.BAND_45;
+ public static final int BAND_46 = android.hardware.radio.V1_5.EutranBands.BAND_46;
+ public static final int BAND_47 = android.hardware.radio.V1_5.EutranBands.BAND_47;
+ public static final int BAND_48 = android.hardware.radio.V1_5.EutranBands.BAND_48;
+ public static final int BAND_49 = android.hardware.radio.V1_5.EutranBands.BAND_49;
+ public static final int BAND_50 = android.hardware.radio.V1_5.EutranBands.BAND_50;
+ public static final int BAND_51 = android.hardware.radio.V1_5.EutranBands.BAND_51;
+ public static final int BAND_52 = android.hardware.radio.V1_5.EutranBands.BAND_52;
+ public static final int BAND_53 = android.hardware.radio.V1_5.EutranBands.BAND_53;
+ public static final int BAND_65 = android.hardware.radio.V1_5.EutranBands.BAND_65;
+ public static final int BAND_66 = android.hardware.radio.V1_5.EutranBands.BAND_66;
+ public static final int BAND_68 = android.hardware.radio.V1_5.EutranBands.BAND_68;
+ public static final int BAND_70 = android.hardware.radio.V1_5.EutranBands.BAND_70;
+ public static final int BAND_71 = android.hardware.radio.V1_5.EutranBands.BAND_71;
+ public static final int BAND_72 = android.hardware.radio.V1_5.EutranBands.BAND_72;
+ public static final int BAND_73 = android.hardware.radio.V1_5.EutranBands.BAND_73;
+ public static final int BAND_74 = android.hardware.radio.V1_5.EutranBands.BAND_74;
+ public static final int BAND_85 = android.hardware.radio.V1_5.EutranBands.BAND_85;
+ public static final int BAND_87 = android.hardware.radio.V1_5.EutranBands.BAND_87;
+ public static final int BAND_88 = android.hardware.radio.V1_5.EutranBands.BAND_88;
+
+ /**
+ * EutranBands
+ *
+ * @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"BAND_"},
+ value = {BAND_1,
+ BAND_2,
+ BAND_3,
+ BAND_4,
+ BAND_5,
+ BAND_6,
+ BAND_7,
+ BAND_8,
+ BAND_9,
+ BAND_10,
+ BAND_11,
+ BAND_12,
+ BAND_13,
+ BAND_14,
+ BAND_17,
+ BAND_18,
+ BAND_19,
+ BAND_20,
+ BAND_21,
+ BAND_22,
+ BAND_23,
+ BAND_24,
+ BAND_25,
+ BAND_26,
+ BAND_27,
+ BAND_28,
+ BAND_30,
+ BAND_31,
+ BAND_33,
+ BAND_34,
+ BAND_35,
+ BAND_36,
+ BAND_37,
+ BAND_38,
+ BAND_39,
+ BAND_40,
+ BAND_41,
+ BAND_42,
+ BAND_43,
+ BAND_44,
+ BAND_45,
+ BAND_46,
+ BAND_47,
+ BAND_48,
+ BAND_49,
+ BAND_50,
+ BAND_51,
+ BAND_52,
+ BAND_53,
+ BAND_65,
+ BAND_66,
+ BAND_68,
+ BAND_70,
+ BAND_71,
+ BAND_72,
+ BAND_73,
+ BAND_74,
+ BAND_85,
+ BAND_87,
+ BAND_88})
+
+ public @interface EutranBands {}
/** @hide */
private EutranBand() {};
}
/**
+ * 3GPP TS 36.101 Table 5.7.3-1 E-UTRA channel numbers.
+ *
+ * @hide
+ */
+ enum EutranBandArfcnFrequency {
+
+ EUTRAN_ARFCN_FREQUENCY_BAND_1(
+ EutranBand.BAND_1, 2110000, 0, 599, 1920000, 18800, 18599),
+ EUTRAN_ARFCN_FREQUENCY_BAND_2(
+ EutranBand.BAND_2, 1930000, 600, 1199, 1850000, 18600, 19199),
+ EUTRAN_ARFCN_FREQUENCY_BAND_3(
+ EutranBand.BAND_3, 1805000, 1200, 1949, 1710000, 19200, 19949),
+ EUTRAN_ARFCN_FREQUENCY_BAND_4(
+ EutranBand.BAND_4, 2110000, 1950, 2399, 1710000, 19950, 20399),
+ EUTRAN_ARFCN_FREQUENCY_BAND_5(
+ EutranBand.BAND_5, 869000, 2400, 2649, 824000, 20400, 20649),
+ EUTRAN_ARFCN_FREQUENCY_BAND_6(
+ EutranBand.BAND_6, 875000, 2650, 2749, 830000, 20650, 20749),
+ EUTRAN_ARFCN_FREQUENCY_BAND_7(
+ EutranBand.BAND_7, 2620000, 2750, 3449, 2500000, 20750, 21449),
+ EUTRAN_ARFCN_FREQUENCY_BAND_8(
+ EutranBand.BAND_8, 925000, 3450, 3799, 880000, 21450, 21799),
+ EUTRAN_ARFCN_FREQUENCY_BAND_9(
+ EutranBand.BAND_9, 1844900, 3800, 4149, 1749900, 21800, 22149),
+ EUTRAN_ARFCN_FREQUENCY_BAND_10(
+ EutranBand.BAND_10, 2110000, 4150, 4749, 1710000, 22150, 22749),
+ EUTRAN_ARFCN_FREQUENCY_BAND_11(
+ EutranBand.BAND_11, 1475900, 4750, 4949, 1427900, 22750, 22949),
+ EUTRAN_ARFCN_FREQUENCY_BAND_12(
+ EutranBand.BAND_12, 729000, 5010, 5179, 699000, 23010, 23179),
+ EUTRAN_ARFCN_FREQUENCY_BAND_13(
+ EutranBand.BAND_13, 746000, 5180, 5279, 777000, 23180, 23279),
+ EUTRAN_ARFCN_FREQUENCY_BAND_14(
+ EutranBand.BAND_14, 758000, 5280, 5379, 788000, 23230, 23379),
+ EUTRAN_ARFCN_FREQUENCY_BAND_17(
+ EutranBand.BAND_17, 734000, 5730, 5849, 704000, 23730, 23849),
+ EUTRAN_ARFCN_FREQUENCY_BAND_18(
+ EutranBand.BAND_18, 860000, 5850, 5999, 815000, 23850, 23999),
+ EUTRAN_ARFCN_FREQUENCY_BAND_19(
+ EutranBand.BAND_19, 875000, 6000, 6149, 830000, 24000, 24149),
+ EUTRAN_ARFCN_FREQUENCY_BAND_20(
+ EutranBand.BAND_20, 791000, 6150, 6449, 832000, 24150, 24449),
+ EUTRAN_ARFCN_FREQUENCY_BAND_21(
+ EutranBand.BAND_21, 1495900, 6450, 6599, 1447900, 24450, 24599),
+ EUTRAN_ARFCN_FREQUENCY_BAND_22(
+ EutranBand.BAND_22, 3510000, 6600, 7399, 3410000, 24600, 25399),
+ EUTRAN_ARFCN_FREQUENCY_BAND_23(
+ EutranBand.BAND_23, 2180000, 7500, 7699, 2000000, 25500, 25699),
+ EUTRAN_ARFCN_FREQUENCY_BAND_24(
+ EutranBand.BAND_24, 1525000, 7700, 8039, 1626500, 25700, 26039),
+ EUTRAN_ARFCN_FREQUENCY_BAND_25(
+ EutranBand.BAND_25, 1930000, 8040, 8689, 1850000, 26040, 26689),
+ EUTRAN_ARFCN_FREQUENCY_BAND_26(
+ EutranBand.BAND_26, 859000, 8690, 9039, 814000, 26690, 27039),
+ EUTRAN_ARFCN_FREQUENCY_BAND_27(
+ EutranBand.BAND_27, 852000, 9040, 9209, 807000, 27040, 27209),
+ EUTRAN_ARFCN_FREQUENCY_BAND_28(
+ EutranBand.BAND_28, 758000, 9210, 9659, 703000, 27210, 27659),
+ EUTRAN_ARFCN_FREQUENCY_BAND_30(
+ EutranBand.BAND_30, 2350000, 9770, 9869, 2305000, 27660, 27759),
+ EUTRAN_ARFCN_FREQUENCY_BAND_31(
+ EutranBand.BAND_31, 462500, 9870, 9919, 452500, 27760, 27809),
+ EUTRAN_ARFCN_FREQUENCY_BAND_33(
+ EutranBand.BAND_33, 1900000, 36000, 36199, 1900000, 36000, 36199),
+ EUTRAN_ARFCN_FREQUENCY_BAND_34(
+ EutranBand.BAND_34, 2010000, 36200, 36349, 2010000, 36200, 36349),
+ EUTRAN_ARFCN_FREQUENCY_BAND_35(
+ EutranBand.BAND_35, 1850000, 36350, 36949, 1850000, 36350, 36949),
+ EUTRAN_ARFCN_FREQUENCY_BAND_36(
+ EutranBand.BAND_36, 1930000, 36950, 37549, 1930000, 36950, 37549),
+ EUTRAN_ARFCN_FREQUENCY_BAND_37(
+ EutranBand.BAND_37, 1910000, 37550, 37749, 1910000, 37550, 37749),
+ EUTRAN_ARFCN_FREQUENCY_BAND_38(
+ EutranBand.BAND_38, 2570000, 37750, 38249, 2570000, 37750, 38249),
+ EUTRAN_ARFCN_FREQUENCY_BAND_39(
+ EutranBand.BAND_39, 1880000, 38250, 38649, 1880000, 38250, 38649),
+ EUTRAN_ARFCN_FREQUENCY_BAND_40(
+ EutranBand.BAND_40, 2300000, 38650, 39649, 2300000, 38650, 39649),
+ EUTRAN_ARFCN_FREQUENCY_BAND_41(
+ EutranBand.BAND_41, 2496000, 39650, 41589, 2496000, 39650, 41589),
+ EUTRAN_ARFCN_FREQUENCY_BAND_42(
+ EutranBand.BAND_42, 3400000, 41950, 43589, 3400000, 41950, 43589),
+ EUTRAN_ARFCN_FREQUENCY_BAND_43(
+ EutranBand.BAND_43, 3600000, 43950, 45589, 3600000, 43950, 45589),
+ EUTRAN_ARFCN_FREQUENCY_BAND_44(
+ EutranBand.BAND_44, 703000, 45590, 46589, 703000, 45590, 46589),
+ EUTRAN_ARFCN_FREQUENCY_BAND_45(
+ EutranBand.BAND_45, 1447000, 46590, 46789, 1447000, 46590, 46789),
+ EUTRAN_ARFCN_FREQUENCY_BAND_46(
+ EutranBand.BAND_46, 5150000, 46790, 54539, 5150000, 46790, 54539),
+ EUTRAN_ARFCN_FREQUENCY_BAND_47(
+ EutranBand.BAND_47, 5855000, 54540, 55239, 5855000, 54540, 55239),
+ EUTRAN_ARFCN_FREQUENCY_BAND_48(
+ EutranBand.BAND_48, 3550000, 55240, 56739, 3550000, 55240, 56739),
+ EUTRAN_ARFCN_FREQUENCY_BAND_49(
+ EutranBand.BAND_49, 3550000, 56740, 58239, 3550000, 56740, 58239),
+ EUTRAN_ARFCN_FREQUENCY_BAND_50(
+ EutranBand.BAND_50, 1432000, 58240, 59089, 1432000, 58240, 59089),
+ EUTRAN_ARFCN_FREQUENCY_BAND_51(
+ EutranBand.BAND_51, 1427000, 59090, 59139, 1427000, 59090, 59139),
+ EUTRAN_ARFCN_FREQUENCY_BAND_52(
+ EutranBand.BAND_52, 3300000, 59140, 60139, 3300000, 59140, 60139),
+ EUTRAN_ARFCN_FREQUENCY_BAND_53(
+ EutranBand.BAND_53, 2483500, 60140, 60254, 2483500, 60140, 60254),
+ EUTRAN_ARFCN_FREQUENCY_BAND_65(
+ EutranBand.BAND_65, 2110000, 65536, 66435, 1920000, 131072, 131971),
+ EUTRAN_ARFCN_FREQUENCY_BAND_66(
+ EutranBand.BAND_66, 2110000, 66436, 67335, 1710000, 131972, 132671),
+ EUTRAN_ARFCN_FREQUENCY_BAND_68(
+ EutranBand.BAND_68, 753000, 67536, 67835, 698000, 132672, 132971),
+ EUTRAN_ARFCN_FREQUENCY_BAND_70(
+ EutranBand.BAND_70, 1995000, 68336, 68585, 1695000, 132972, 133121),
+ EUTRAN_ARFCN_FREQUENCY_BAND_71(
+ EutranBand.BAND_71, 617000, 68586, 68935, 663000, 133122, 133471),
+ EUTRAN_ARFCN_FREQUENCY_BAND_72(
+ EutranBand.BAND_72, 461000, 68936, 68985, 451000, 133472, 133521),
+ EUTRAN_ARFCN_FREQUENCY_BAND_73(
+ EutranBand.BAND_73, 460000, 68986, 69035, 450000, 133522, 133571),
+ EUTRAN_ARFCN_FREQUENCY_BAND_74(
+ EutranBand.BAND_74, 1475000, 69036, 69465, 1427000, 133572, 134001),
+ EUTRAN_ARFCN_FREQUENCY_BAND_85(
+ EutranBand.BAND_85, 728000, 70366, 70545, 698000, 134002, 134181),
+ EUTRAN_ARFCN_FREQUENCY_BAND_87(
+ EutranBand.BAND_87, 420000, 70546, 70595, 410000, 134182, 134231),
+ EUTRAN_ARFCN_FREQUENCY_BAND_88(
+ EutranBand.BAND_88, 422000, 70596, 70645, 412000, 134231, 134280);
+
+ EutranBandArfcnFrequency(int band, int downlinkLowKhz, int downlinkOffset,
+ int downlinkRange, int uplinkLowKhz, int uplinkOffset,
+ int uplinkRange) {
+ this.band = band;
+ this.downlinkLowKhz = downlinkLowKhz;
+ this.downlinkOffset = downlinkOffset;
+ this.uplinkLowKhz = uplinkLowKhz;
+ this.uplinkOffset = uplinkOffset;
+ this.downlinkRange = downlinkRange;
+ this.uplinkRange = uplinkRange;
+ }
+
+ int band;
+ int downlinkLowKhz;
+ int downlinkOffset;
+ int uplinkLowKhz;
+ int uplinkOffset;
+ int downlinkRange;
+ int uplinkRange;
+ }
+
+ /**
* Frequency bands for CDMA2000.
* http://www.3gpp2.org/Public_html/Specs/C.S0057-E_v1.0_Bandclass_Specification.pdf
* @hide
@@ -320,7 +693,7 @@
* https://www.etsi.org/deliver/etsi_ts/138100_138199/13810102/15.08.00_60/ts_13810102v150800p.pdf
*/
public static final class NgranBands {
- /** 3GPP TS 38.101-1, Version 16.2.0, Table 5.2-1: FR1 bands */
+ /** 3GPP TS 38.101-1, Version 16.5.0, Table 5.2-1: FR1 bands */
public static final int BAND_1 = android.hardware.radio.V1_5.NgranBands.BAND_1;
public static final int BAND_2 = android.hardware.radio.V1_5.NgranBands.BAND_2;
public static final int BAND_3 = android.hardware.radio.V1_5.NgranBands.BAND_3;
@@ -332,6 +705,7 @@
public static final int BAND_18 = android.hardware.radio.V1_5.NgranBands.BAND_18;
public static final int BAND_20 = android.hardware.radio.V1_5.NgranBands.BAND_20;
public static final int BAND_25 = android.hardware.radio.V1_5.NgranBands.BAND_25;
+ public static final int BAND_26 = android.hardware.radio.V1_6.NgranBands.BAND_26;
public static final int BAND_28 = android.hardware.radio.V1_5.NgranBands.BAND_28;
public static final int BAND_29 = android.hardware.radio.V1_5.NgranBands.BAND_29;
public static final int BAND_30 = android.hardware.radio.V1_5.NgranBands.BAND_30;
@@ -340,9 +714,11 @@
public static final int BAND_39 = android.hardware.radio.V1_5.NgranBands.BAND_39;
public static final int BAND_40 = android.hardware.radio.V1_5.NgranBands.BAND_40;
public static final int BAND_41 = android.hardware.radio.V1_5.NgranBands.BAND_41;
+ public static final int BAND_46 = android.hardware.radio.V1_6.NgranBands.BAND_46;
public static final int BAND_48 = android.hardware.radio.V1_5.NgranBands.BAND_48;
public static final int BAND_50 = android.hardware.radio.V1_5.NgranBands.BAND_50;
public static final int BAND_51 = android.hardware.radio.V1_5.NgranBands.BAND_51;
+ public static final int BAND_53 = android.hardware.radio.V1_6.NgranBands.BAND_53;
public static final int BAND_65 = android.hardware.radio.V1_5.NgranBands.BAND_65;
public static final int BAND_66 = android.hardware.radio.V1_5.NgranBands.BAND_66;
public static final int BAND_70 = android.hardware.radio.V1_5.NgranBands.BAND_70;
@@ -366,6 +742,7 @@
public static final int BAND_93 = android.hardware.radio.V1_5.NgranBands.BAND_93;
public static final int BAND_94 = android.hardware.radio.V1_5.NgranBands.BAND_94;
public static final int BAND_95 = android.hardware.radio.V1_5.NgranBands.BAND_95;
+ public static final int BAND_96 = android.hardware.radio.V1_6.NgranBands.BAND_96;
/** 3GPP TS 38.101-2, Version 16.2.0, Table 5.2-1: FR2 bands */
public static final int BAND_257 = android.hardware.radio.V1_5.NgranBands.BAND_257;
@@ -390,6 +767,7 @@
BAND_18,
BAND_20,
BAND_25,
+ BAND_26,
BAND_28,
BAND_29,
BAND_30,
@@ -398,9 +776,11 @@
BAND_39,
BAND_40,
BAND_41,
+ BAND_46,
BAND_48,
BAND_50,
BAND_51,
+ BAND_53,
BAND_65,
BAND_66,
BAND_70,
@@ -424,6 +804,7 @@
BAND_93,
BAND_94,
BAND_95,
+ BAND_96,
BAND_257,
BAND_258,
BAND_260,
@@ -464,7 +845,8 @@
value = {
FREQUENCY_RANGE_GROUP_UNKNOWN,
FREQUENCY_RANGE_GROUP_1,
- FREQUENCY_RANGE_GROUP_2})
+ FREQUENCY_RANGE_GROUP_2
+ })
public @interface FrequencyRangeGroup {}
/**
@@ -489,6 +871,7 @@
case BAND_18:
case BAND_20:
case BAND_25:
+ case BAND_26:
case BAND_28:
case BAND_29:
case BAND_30:
@@ -497,9 +880,11 @@
case BAND_39:
case BAND_40:
case BAND_41:
+ case BAND_46:
case BAND_48:
case BAND_50:
case BAND_51:
+ case BAND_53:
case BAND_65:
case BAND_66:
case BAND_70:
@@ -523,6 +908,7 @@
case BAND_93:
case BAND_94:
case BAND_95:
+ case BAND_96:
return FREQUENCY_RANGE_GROUP_1;
case BAND_257:
case BAND_258:
@@ -538,6 +924,33 @@
private NgranBands() {}
}
+ /**
+ * 3GPP TS 38.104 Table 5.4.2.1-1 NR-ARFCN parameters for the global frequency raster.
+ *
+ * @hide
+ */
+ enum NgranArfcnFrequency {
+
+ NGRAN_ARFCN_FREQUENCY_RANGE_1(5, 0, 0, 0, 599999),
+ NGRAN_ARFCN_FREQUENCY_RANGE_2(15, 3000000, 600000, 600000, 2016666),
+ NGRAN_ARFCN_FREQUENCY_RANGE_3(60, 24250080, 2016667, 2016667, 3279165);
+
+ NgranArfcnFrequency(int globalKhz, int rangeOffset, int arfcnOffset,
+ int rangeFirst, int rangeLast) {
+ this.globalKhz = globalKhz;
+ this.rangeOffset = rangeOffset;
+ this.arfcnOffset = arfcnOffset;
+ this.rangeFirst = rangeFirst;
+ this.rangeLast = rangeLast;
+ }
+
+ int globalKhz;
+ int rangeOffset;
+ int arfcnOffset;
+ int rangeFirst;
+ int rangeLast;
+ }
+
/** @hide */
private AccessNetworkConstants() {};
}
diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java
index 7661a32..f29f3bd 100644
--- a/telephony/java/android/telephony/AccessNetworkUtils.java
+++ b/telephony/java/android/telephony/AccessNetworkUtils.java
@@ -4,12 +4,20 @@
import static android.telephony.ServiceState.DUPLEX_MODE_TDD;
import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN;
+import android.telephony.AccessNetworkConstants.EutranBandArfcnFrequency;
import android.telephony.AccessNetworkConstants.EutranBand;
import android.telephony.AccessNetworkConstants.GeranBand;
+import android.telephony.AccessNetworkConstants.GeranBandArfcnFrequency;
+import android.telephony.AccessNetworkConstants.NgranArfcnFrequency;
+import android.telephony.AccessNetworkConstants.NgranBands;
import android.telephony.AccessNetworkConstants.UtranBand;
+import android.telephony.AccessNetworkConstants.UtranBandArfcnFrequency;
import android.telephony.ServiceState.DuplexMode;
+import android.util.Log;
import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
/**
* Utilities to map between radio constants.
@@ -22,9 +30,27 @@
private AccessNetworkUtils() {}
public static final int INVALID_BAND = -1;
+ public static final int INVALID_FREQUENCY = -1;
/** ISO country code of Japan. */
private static final String JAPAN_ISO_COUNTRY_CODE = "jp";
+ private static final String TAG = "AccessNetworkUtils";
+
+ private static final int FREQUENCY_KHZ = 1000;
+ private static final int FREQUENCY_RANGE_LOW_KHZ = 1000000;
+ private static final int FREQUENCY_RANGE_MID_KHZ = 3000000;
+ private static final int FREQUENCY_RANGE_HIGH_KHZ = 6000000;
+
+ private static final Set<Integer> UARFCN_NOT_GENERAL_BAND;
+ static {
+ UARFCN_NOT_GENERAL_BAND = new HashSet<Integer>();
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_A);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_B);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_C);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_D);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_E);
+ UARFCN_NOT_GENERAL_BAND.add(UtranBand.BAND_F);
+ }
/**
* Gets the duplex mode for the given EUTRAN operating band.
@@ -325,4 +351,403 @@
}
return INVALID_BAND;
}
+
+ /**
+ * Get geran bands from {@link PhysicalChannelConfig#getBand()}
+ */
+ public static int getFrequencyRangeGroupFromGeranBand(@GeranBand.GeranBands int band) {
+ switch (band) {
+ case GeranBand.BAND_T380:
+ case GeranBand.BAND_T410:
+ case GeranBand.BAND_450:
+ case GeranBand.BAND_480:
+ case GeranBand.BAND_710:
+ case GeranBand.BAND_750:
+ case GeranBand.BAND_T810:
+ case GeranBand.BAND_850:
+ case GeranBand.BAND_P900:
+ case GeranBand.BAND_E900:
+ case GeranBand.BAND_R900:
+ case GeranBand.BAND_ER900:
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ case GeranBand.BAND_DCS1800:
+ case GeranBand.BAND_PCS1900:
+ return ServiceState.FREQUENCY_RANGE_MID;
+ default:
+ return ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Get utran bands from {@link PhysicalChannelConfig#getBand()}
+ */
+ public static int getFrequencyRangeGroupFromUtranBand(@UtranBand.UtranBands int band) {
+ switch (band) {
+ case UtranBand.BAND_5:
+ case UtranBand.BAND_6:
+ case UtranBand.BAND_8:
+ case UtranBand.BAND_12:
+ case UtranBand.BAND_13:
+ case UtranBand.BAND_14:
+ case UtranBand.BAND_19:
+ case UtranBand.BAND_20:
+ case UtranBand.BAND_26:
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ case UtranBand.BAND_1:
+ case UtranBand.BAND_2:
+ case UtranBand.BAND_3:
+ case UtranBand.BAND_4:
+ case UtranBand.BAND_7:
+ case UtranBand.BAND_9:
+ case UtranBand.BAND_10:
+ case UtranBand.BAND_11:
+ case UtranBand.BAND_21:
+ case UtranBand.BAND_25:
+ case UtranBand.BAND_A:
+ case UtranBand.BAND_B:
+ case UtranBand.BAND_C:
+ case UtranBand.BAND_D:
+ case UtranBand.BAND_E:
+ case UtranBand.BAND_F:
+ return ServiceState.FREQUENCY_RANGE_MID;
+ case UtranBand.BAND_22:
+ return ServiceState.FREQUENCY_RANGE_HIGH;
+ default:
+ return ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Get eutran bands from {@link PhysicalChannelConfig#getBand()}
+ * 3GPP TS 36.101 Table 5.5 EUTRA operating bands
+ */
+ public static int getFrequencyRangeGroupFromEutranBand(@EutranBand.EutranBands int band) {
+ switch (band) {
+ case EutranBand.BAND_5:
+ case EutranBand.BAND_6:
+ case EutranBand.BAND_8:
+ case EutranBand.BAND_12:
+ case EutranBand.BAND_13:
+ case EutranBand.BAND_14:
+ case EutranBand.BAND_17:
+ case EutranBand.BAND_18:
+ case EutranBand.BAND_19:
+ case EutranBand.BAND_20:
+ case EutranBand.BAND_26:
+ case EutranBand.BAND_27:
+ case EutranBand.BAND_28:
+ case EutranBand.BAND_31:
+ case EutranBand.BAND_44:
+ case EutranBand.BAND_50:
+ case EutranBand.BAND_51:
+ case EutranBand.BAND_68:
+ case EutranBand.BAND_71:
+ case EutranBand.BAND_72:
+ case EutranBand.BAND_73:
+ case EutranBand.BAND_85:
+ case EutranBand.BAND_87:
+ case EutranBand.BAND_88:
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ case EutranBand.BAND_1:
+ case EutranBand.BAND_2:
+ case EutranBand.BAND_3:
+ case EutranBand.BAND_4:
+ case EutranBand.BAND_7:
+ case EutranBand.BAND_9:
+ case EutranBand.BAND_10:
+ case EutranBand.BAND_11:
+ case EutranBand.BAND_21:
+ case EutranBand.BAND_23:
+ case EutranBand.BAND_24:
+ case EutranBand.BAND_25:
+ case EutranBand.BAND_30:
+ case EutranBand.BAND_33:
+ case EutranBand.BAND_34:
+ case EutranBand.BAND_35:
+ case EutranBand.BAND_36:
+ case EutranBand.BAND_37:
+ case EutranBand.BAND_38:
+ case EutranBand.BAND_39:
+ case EutranBand.BAND_40:
+ case EutranBand.BAND_41:
+ case EutranBand.BAND_45:
+ case EutranBand.BAND_53:
+ case EutranBand.BAND_65:
+ case EutranBand.BAND_66:
+ case EutranBand.BAND_70:
+ case EutranBand.BAND_74:
+ return ServiceState.FREQUENCY_RANGE_MID;
+ case EutranBand.BAND_22:
+ case EutranBand.BAND_42:
+ case EutranBand.BAND_43:
+ case EutranBand.BAND_46:
+ case EutranBand.BAND_47:
+ case EutranBand.BAND_48:
+ case EutranBand.BAND_49:
+ case EutranBand.BAND_52:
+ return ServiceState.FREQUENCY_RANGE_HIGH;
+ default:
+ return ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Get ngran band from {@link PhysicalChannelConfig#getBand()}
+ * 3GPP TS 38.104 Table 5.2-1 NR operating bands in FR1
+ * 3GPP TS 38.104 Table 5.2-2 NR operating bands in FR2
+ */
+ public static int getFrequencyRangeGroupFromNrBand(@NgranBands.NgranBand int band) {
+ switch (band) {
+ case NgranBands.BAND_5:
+ case NgranBands.BAND_8:
+ case NgranBands.BAND_12:
+ case NgranBands.BAND_14:
+ case NgranBands.BAND_18:
+ case NgranBands.BAND_20:
+ case NgranBands.BAND_26:
+ case NgranBands.BAND_28:
+ case NgranBands.BAND_29:
+ case NgranBands.BAND_71:
+ case NgranBands.BAND_81:
+ case NgranBands.BAND_82:
+ case NgranBands.BAND_83:
+ case NgranBands.BAND_89:
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ case NgranBands.BAND_1:
+ case NgranBands.BAND_2:
+ case NgranBands.BAND_3:
+ case NgranBands.BAND_7:
+ case NgranBands.BAND_25:
+ case NgranBands.BAND_30:
+ case NgranBands.BAND_34:
+ case NgranBands.BAND_38:
+ case NgranBands.BAND_39:
+ case NgranBands.BAND_40:
+ case NgranBands.BAND_41:
+ case NgranBands.BAND_50:
+ case NgranBands.BAND_51:
+ case NgranBands.BAND_53:
+ case NgranBands.BAND_65:
+ case NgranBands.BAND_66:
+ case NgranBands.BAND_70:
+ case NgranBands.BAND_74:
+ case NgranBands.BAND_75:
+ case NgranBands.BAND_76:
+ case NgranBands.BAND_80:
+ case NgranBands.BAND_84:
+ case NgranBands.BAND_86:
+ case NgranBands.BAND_90:
+ case NgranBands.BAND_91:
+ case NgranBands.BAND_92:
+ case NgranBands.BAND_93:
+ case NgranBands.BAND_94:
+ case NgranBands.BAND_95:
+ return ServiceState.FREQUENCY_RANGE_MID;
+ case NgranBands.BAND_46:
+ case NgranBands.BAND_48:
+ case NgranBands.BAND_77:
+ case NgranBands.BAND_78:
+ case NgranBands.BAND_79:
+ return ServiceState.FREQUENCY_RANGE_HIGH;
+ case NgranBands.BAND_96:
+ case NgranBands.BAND_257:
+ case NgranBands.BAND_258:
+ case NgranBands.BAND_260:
+ case NgranBands.BAND_261:
+ return ServiceState.FREQUENCY_RANGE_MMWAVE;
+ default:
+ return ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ }
+ }
+
+ /**
+ * 3GPP TS 38.104 Table 5.4.2.1-1 NR-ARFCN parameters for the global frequency raster.
+ * Formula of NR-ARFCN convert to actual frequency:
+ * Actual frequency(kHz) = (RANGE_OFFSET + GLOBAL_KHZ * (ARFCN - ARFCN_OFFSET))
+ */
+ public static int getFrequencyFromNrArfcn(int nrArfcn) {
+
+ int globalKhz = 0;
+ int rangeOffset = 0;
+ int arfcnOffset = 0;
+ for (NgranArfcnFrequency nrArfcnFrequency : AccessNetworkConstants.
+ NgranArfcnFrequency.values()) {
+ if (nrArfcn >= nrArfcnFrequency.rangeFirst
+ && nrArfcn <= nrArfcnFrequency.rangeLast) {
+ globalKhz = nrArfcnFrequency.globalKhz;
+ rangeOffset = nrArfcnFrequency.rangeOffset;
+ arfcnOffset = nrArfcnFrequency.arfcnOffset;
+ break;
+ }
+ }
+ return rangeOffset + globalKhz * (nrArfcn - arfcnOffset);
+ }
+
+ /**
+ * Get actual frequency from E-UTRA ARFCN.
+ */
+ public static int getFrequencyFromEarfcn(int band, int earfcn, boolean isUplink) {
+
+ int low = 0;
+ int offset = 0;
+ for (EutranBandArfcnFrequency earfcnFrequency : EutranBandArfcnFrequency.values()) {
+ if (band == earfcnFrequency.band) {
+ if (isInEarfcnRange(earfcn, earfcnFrequency, isUplink)) {
+ low = isUplink ? earfcnFrequency.uplinkLowKhz : earfcnFrequency.downlinkLowKhz;
+ offset = isUplink ? earfcnFrequency.uplinkOffset
+ : earfcnFrequency.downlinkOffset;
+ break;
+ } else {
+ Log.e(TAG, "Band and the range of EARFCN are not consistent.");
+ return INVALID_FREQUENCY;
+ }
+ }
+ }
+ return convertEarfcnToFrequency(low, earfcn, offset);
+ }
+
+ /**
+ * 3GPP TS 36.101 Table 5.7.3-1 E-UTRA channel numbers.
+ * Formula of E-UTRA ARFCN convert to actual frequency:
+ * Actual frequency(kHz) = (DOWNLINK_LOW + 0.1 * (ARFCN - DOWNLINK_OFFSET)) * FREQUENCY_KHZ
+ * Actual frequency(kHz) = (UPLINK_LOW + 0.1 * (ARFCN - UPLINK_OFFSET)) * FREQUENCY_KHZ
+ */
+ private static int convertEarfcnToFrequency(int low, int earfcn, int offset) {
+ return low + 100 * (earfcn - offset);
+ }
+
+ private static boolean isInEarfcnRange(int earfcn, EutranBandArfcnFrequency earfcnFrequency,
+ boolean isUplink) {
+ if (isUplink) {
+ return earfcn >= earfcnFrequency.uplinkOffset && earfcn <= earfcnFrequency.uplinkRange;
+ } else {
+ return earfcn >= earfcnFrequency.downlinkOffset
+ && earfcn <= earfcnFrequency.downlinkRange;
+ }
+ }
+
+ /**
+ * Get actual frequency from UTRA ARFCN.
+ */
+ public static int getFrequencyFromUarfcn(int band, int uarfcn, boolean isUplink) {
+
+ int offsetKhz = 0;
+ for (UtranBandArfcnFrequency uarfcnFrequency : AccessNetworkConstants.
+ UtranBandArfcnFrequency.values()) {
+ if (band == uarfcnFrequency.band) {
+ if (isInUarfcnRange(uarfcn, uarfcnFrequency, isUplink)) {
+ offsetKhz = isUplink ? uarfcnFrequency.uplinkOffset
+ : uarfcnFrequency.downlinkOffset;
+ break;
+ } else {
+ Log.e(TAG, "Band and the range of UARFCN are not consistent.");
+ return INVALID_FREQUENCY;
+ }
+ }
+ }
+
+ if (!UARFCN_NOT_GENERAL_BAND.contains(band)) {
+ return convertUarfcnToFrequency(offsetKhz, uarfcn);
+ } else {
+ return convertUarfcnTddToFrequency(band, uarfcn);
+ }
+ }
+
+ /**
+ * 3GPP TS 25.101, Table 5.1 UARFCN definition (general).
+ * Formula of UTRA ARFCN convert to actual frequency:
+ * For general bands:
+ * Downlink actual frequency(kHz) = (DOWNLINK_OFFSET + 0.2 * ARFCN) * FREQUENCY_KHZ
+ * Uplink actual frequency(kHz) = (UPLINK_OFFSET + 0.2 * ARFCN) * FREQUENCY_KHZ
+ */
+ private static int convertUarfcnToFrequency(int offsetKhz, int uarfcn) {
+ return offsetKhz + (200 * uarfcn);
+ }
+
+ /**
+ * 3GPP TS 25.102, Table 5.2 UTRA Absolute Radio Frequency Channel Number 1.28 Mcps TDD Option.
+ * For FDD bands A, B, C, E, F:
+ * Actual frequency(kHz) = 5 * ARFCN * FREQUENCY_KHZ
+ * For TDD bands D:
+ * Actual frequency(kHz) = (5 * (ARFCN - 2150.1MHz)) * FREQUENCY_KHZ
+ */
+ private static int convertUarfcnTddToFrequency(int band, int uarfcn) {
+ if (band != UtranBand.BAND_D) {
+ return 5 * uarfcn * FREQUENCY_KHZ;
+ } else {
+ return 5 * ((FREQUENCY_KHZ * uarfcn) - 2150100);
+ }
+ }
+
+ private static boolean isInUarfcnRange(int uarfcn, UtranBandArfcnFrequency uarfcnFrequency,
+ boolean isUplink) {
+ if (isUplink) {
+ return uarfcn >= uarfcnFrequency.uplinkRangeFirst
+ && uarfcn <= uarfcnFrequency.uplinkRangeLast;
+ } else {
+ if (uarfcnFrequency.downlinkRangeFirst != 0 && uarfcnFrequency.downlinkRangeLast != 0) {
+ return uarfcn >= uarfcnFrequency.downlinkRangeFirst
+ && uarfcn <= uarfcnFrequency.downlinkRangeLast;
+ } else {
+ // BAND_C, BAND_D, BAND_E and BAND_F do not have the downlink range.
+ return true;
+ }
+ }
+ }
+
+ /**
+ * Get actual frequency from GERAN ARFCN.
+ */
+ public static int getFrequencyFromArfcn(int band, int arfcn, boolean isUplink) {
+
+ int uplinkFrequencyFirst = 0;
+ int arfcnOffset = 0;
+ int downlinkOffset = 0;
+ int frequency = 0;
+ for (GeranBandArfcnFrequency arfcnFrequency : AccessNetworkConstants.
+ GeranBandArfcnFrequency.values()) {
+ if (band == arfcnFrequency.band) {
+ if (arfcn >= arfcnFrequency.arfcnRangeFirst
+ && arfcn <= arfcnFrequency.arfcnRangeLast) {
+ uplinkFrequencyFirst = arfcnFrequency.uplinkFrequencyFirst;
+ downlinkOffset = arfcnFrequency.downlinkOffset;
+ arfcnOffset = arfcnFrequency.arfcnOffset;
+ frequency = convertArfcnToFrequency(arfcn, uplinkFrequencyFirst,
+ arfcnOffset);
+ break;
+ } else {
+ Log.e(TAG, "Band and the range of ARFCN are not consistent.");
+ return INVALID_FREQUENCY;
+ }
+ }
+ }
+
+ return isUplink ? frequency : frequency + downlinkOffset;
+ }
+
+ /**
+ * 3GPP TS 45.005 Table 2-1 Dynamically mapped ARFCN
+ * Formula of Geran ARFCN convert to actual frequency:
+ * Uplink actual frequency(kHz) =
+ * (UPLINK_FREQUENCY_FIRST + 0.2 * (ARFCN - ARFCN_RANGE_FIRST)) * FREQUENCY_KHZ
+ * Downlink actual frequency(kHz) = Uplink actual frequency + 10
+ */
+ private static int convertArfcnToFrequency(int arfcn, int uplinkFrequencyFirstKhz,
+ int arfcnOffset) {
+ return uplinkFrequencyFirstKhz + 200 * (arfcn - arfcnOffset);
+ }
+
+ public static int getFrequencyRangeFromArfcn(int frequency) {
+ if (frequency < FREQUENCY_RANGE_LOW_KHZ) {
+ return ServiceState.FREQUENCY_RANGE_LOW;
+ } else if (frequency < FREQUENCY_RANGE_MID_KHZ
+ && frequency >= FREQUENCY_RANGE_LOW_KHZ) {
+ return ServiceState.FREQUENCY_RANGE_MID;
+ } else if (frequency < FREQUENCY_RANGE_HIGH_KHZ
+ && frequency >= FREQUENCY_RANGE_MID_KHZ) {
+ return ServiceState.FREQUENCY_RANGE_HIGH;
+ } else {
+ return ServiceState.FREQUENCY_RANGE_MMWAVE;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 7e019cc..426da52 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3591,6 +3591,28 @@
*/
public static final String ENABLE_EAP_METHOD_PREFIX_BOOL = "enable_eap_method_prefix_bool";
+
+ /**
+ * Configs used by ImsServiceEntitlement.
+ */
+ public static final class ImsServiceEntitlement {
+ private ImsServiceEntitlement() {}
+
+ /** Prefix of all ImsServiceEntitlement.KEY_* constants. */
+ public static final String KEY_PREFIX = "imsserviceentitlement.";
+
+
+ /** The address of the entitlement configuration server. */
+ public static final String KEY_AES_URL_STRING = KEY_PREFIX + "aes_url_string";
+
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putString(KEY_AES_URL_STRING, "");
+ return defaults;
+ }
+ }
+
/**
* GPS configs. See the GNSS HAL documentation for more details.
*/
@@ -4621,6 +4643,13 @@
*/
public static final String KEY_USE_ACS_FOR_RCS_BOOL = "use_acs_for_rcs_bool";
+ /**
+ * Indicates temporarily unmetered mobile data is supported by the carrier.
+ * @hide
+ */
+ public static final String KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL =
+ "network_temp_not_metered_supported_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -5119,6 +5148,7 @@
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000);
/* Default value is 60 seconds. */
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG, 60000);
+ sDefaults.putAll(ImsServiceEntitlement.getDefaults());
sDefaults.putAll(Gps.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
new int[] {
@@ -5170,6 +5200,7 @@
sDefaults.putString(KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING, "");
sDefaults.putBoolean(KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED, false);
sDefaults.putBoolean(KEY_USE_ACS_FOR_RCS_BOOL, false);
+ sDefaults.putBoolean(KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index ed09d53..1273aa3a 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -478,7 +478,9 @@
/**
* Compare phone numbers a and b, return true if they're identical enough for caller ID purposes.
+ * @deprecated use {@link #areSamePhoneNumber(String, String, String)} instead
*/
+ @Deprecated
public static boolean compare(String a, String b) {
// We've used loose comparation at least Eclair, which may change in the future.
@@ -489,7 +491,9 @@
* Compare phone numbers a and b, and return true if they're identical
* enough for caller ID purposes. Checks a resource to determine whether
* to use a strict or loose comparison algorithm.
+ * @deprecated use {@link #areSamePhoneNumber(String, String, String)} instead
*/
+ @Deprecated
public static boolean compare(Context context, String a, String b) {
boolean useStrict = context.getResources().getBoolean(
com.android.internal.R.bool.config_use_strict_phone_number_comparation);
@@ -3218,7 +3222,7 @@
}
// The conversion map is not defined (this is default). Skip conversion.
- if (sConvertToEmergencyMap == null || sConvertToEmergencyMap.length == 0 ) {
+ if (sConvertToEmergencyMap == null || sConvertToEmergencyMap.length == 0) {
return number;
}
@@ -3254,4 +3258,47 @@
}
return number;
}
+
+ /**
+ * Determines if two phone numbers are the same.
+ * <p>
+ * Matching is based on <a href="https://github.com/google/libphonenumber>libphonenumber</a>.
+ * Unlike {@link #compare(String, String)}, matching takes into account national
+ * dialing plans rather than simply matching the last 7 digits of the two phone numbers. As a
+ * result, it is expected that some numbers which would match using the previous method will no
+ * longer match using this new approach.
+ *
+ * @param number1
+ * @param number2
+ * @param defaultCountryIso The lowercase two letter ISO 3166-1 country code. Used when parsing
+ * the phone numbers where it is not possible to determine the country
+ * associated with a phone number based on the number alone. It
+ * is recommended to pass in
+ * {@link TelephonyManager#getNetworkCountryIso()}.
+ * @return True if the two given phone number are same.
+ */
+ public static boolean areSamePhoneNumber(@NonNull String number1,
+ @NonNull String number2, @NonNull String defaultCountryIso) {
+ PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+ PhoneNumber n1;
+ PhoneNumber n2;
+ defaultCountryIso = defaultCountryIso.toUpperCase();
+ try {
+ n1 = util.parseAndKeepRawInput(number1, defaultCountryIso);
+ n2 = util.parseAndKeepRawInput(number2, defaultCountryIso);
+ } catch (NumberParseException e) {
+ return false;
+ }
+
+ PhoneNumberUtil.MatchType matchType = util.isNumberMatch(n1, n2);
+ if (matchType == PhoneNumberUtil.MatchType.EXACT_MATCH
+ || matchType == PhoneNumberUtil.MatchType.NSN_MATCH) {
+ return true;
+ } else if (matchType == PhoneNumberUtil.MatchType.SHORT_NSN_MATCH) {
+ return (n1.getNationalNumber() == n2.getNationalNumber()
+ && n1.getCountryCode() == n2.getCountryCode());
+ } else {
+ return false;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index 95c69ba..b359ebe 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.NetworkType;
@@ -56,6 +55,18 @@
/** Physical Cell Id is unknown. */
public static final int PHYSICAL_CELL_ID_UNKNOWN = -1;
+ /** Physical Cell Id's maximum value is 1007. */
+ public static final int PHYSICAL_CELL_ID_MAXIMUM_VALUE = 1007;
+
+ /** Cell bandwidth is unknown. */
+ public static final int CELL_BANDWIDTH_UNKNOWN = 0;
+
+ /** The frequency is unknown. */
+ public static final int FREQUENCY_UNKNOWN = -1;
+
+ /** The band is unknown. */
+ public static final int BAND_UNKNOWN = 0;
+
/**
* Connection status of the cell.
*
@@ -65,15 +76,20 @@
private int mCellConnectionStatus;
/**
- * Cell bandwidth, in kHz.
+ * Downlink cell bandwidth, in kHz.
*/
private int mCellBandwidthDownlinkKhz;
/**
+ * Uplink cell bandwidth, in kHz.
+ */
+ private int mCellBandwidthUplinkKhz;
+
+ /**
* The radio technology for this physical channel.
*/
@NetworkType
- private int mRat;
+ private int mNetworkType;
/**
* The rough frequency range for this physical channel.
@@ -82,9 +98,24 @@
private int mFrequencyRange;
/**
- * The absolute radio frequency channel number, {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
+ * The frequency of Downlink.
*/
- private int mChannelNumber;
+ private int mDownlinkFrequency;
+
+ /**
+ * The frequency of Uplink.
+ */
+ private int mUplinkFrequency;
+
+ /**
+ * Downlink Absolute Radio Frequency Channel Number
+ */
+ private int mDownlinkChannelNumber;
+
+ /**
+ * Uplink Absolute Radio Frequency Channel Number
+ */
+ private int mUplinkChannelNumber;
/**
* A list of data calls mapped to this physical channel. An empty list means the physical
@@ -98,6 +129,11 @@
*/
private int mPhysicalCellId;
+ /**
+ * This is the band which is being used.
+ */
+ private int mBand;
+
@Override
public int describeContents() {
return 0;
@@ -107,27 +143,39 @@
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mCellConnectionStatus);
dest.writeInt(mCellBandwidthDownlinkKhz);
- dest.writeInt(mRat);
- dest.writeInt(mChannelNumber);
+ dest.writeInt(mCellBandwidthUplinkKhz);
+ dest.writeInt(mNetworkType);
+ dest.writeInt(mDownlinkChannelNumber);
+ dest.writeInt(mUplinkChannelNumber);
dest.writeInt(mFrequencyRange);
dest.writeIntArray(mContextIds);
dest.writeInt(mPhysicalCellId);
+ dest.writeInt(mBand);
}
/**
- * @return Cell bandwidth, in kHz
+ * @return Downlink cell bandwidth in kHz, {@link #CELL_BANDWIDTH_UNKNOWN} if unknown.
*/
- public int getCellBandwidthDownlink() {
+ @IntRange(from = 1)
+ public int getCellBandwidthDownlinkKhz() {
return mCellBandwidthDownlinkKhz;
}
/**
+ * @return Uplink cell bandwidth in kHz, {@link #CELL_BANDWIDTH_UNKNOWN} if unknown.
+ */
+ @IntRange(from = 1)
+ public int getCellBandwidthUplinkKhz() {
+ return mCellBandwidthUplinkKhz;
+ }
+
+ /**
* Get the list of data call ids mapped to this physical channel. This list is sorted into
* ascending numerical order. Each id in this list must match the id in
* {@link com.android.internal.telephony.dataconnection.DataConnection}. An empty list means the
* physical channel has no data call mapped to it.
*
- * @return an integer list indicates the data call ids.
+ * @return an integer list indicates the data call ids,
* @hide
*/
public int[] getContextIds() {
@@ -135,7 +183,18 @@
}
/**
- * @return the rough frequency range for this physical channel.
+ * @return the absolute radio frequency channel number for this physical channel,
+ * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
+ * @deprecated Use {@link #getDownlinkChannelNumber()} to get the channel number.
+ */
+ @Deprecated
+ public int getChannelNumber() {
+ return getDownlinkChannelNumber();
+ }
+
+ /**
+ * @return the rough frequency range for this physical channel,
+ * {@link ServiceState#FREQUENCY_RANGE_UNKNOWN} if unknown.
* @see {@link ServiceState#FREQUENCY_RANGE_LOW}
* @see {@link ServiceState#FREQUENCY_RANGE_MID}
* @see {@link ServiceState#FREQUENCY_RANGE_HIGH}
@@ -148,11 +207,48 @@
}
/**
- * @return the absolute radio frequency channel number for this physical channel,
+ * @return Downlink Absolute Radio Frequency Channel Number,
* {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
*/
- public int getChannelNumber() {
- return mChannelNumber;
+ @IntRange(from = 0)
+ public int getDownlinkChannelNumber() {
+ return mDownlinkChannelNumber;
+ }
+
+ /**
+ * @return Uplink Absolute Radio Frequency Channel Number,
+ * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
+ */
+ @IntRange(from = 0)
+ public int getUplinkChannelNumber() {
+ return mUplinkChannelNumber;
+ }
+
+ /**
+ * The valid bands are {@link AccessNetworkConstants.GeranBand},
+ * {@link AccessNetworkConstants.UtranBand}, {@link AccessNetworkConstants.EutranBand} and
+ * {@link AccessNetworkConstants.NgranBands}.
+ *
+ * @return the frequency band, {@link #BAND_UNKNOWN} if unknown. */
+ @IntRange(from = 1, to = 261)
+ public int getBand() {
+ return mBand;
+ }
+
+ /**
+ * @return The downlink frequency in kHz, {@link #FREQUENCY_UNKNOWN} if unknown.
+ */
+ @IntRange(from = 0)
+ public int getDownlinkFrequencyKhz() {
+ return mDownlinkFrequency;
+ }
+
+ /**
+ * @return The uplink frequency in kHz, {@link #FREQUENCY_UNKNOWN} if unknown.
+ */
+ @IntRange(from = 0)
+ public int getUplinkFrequencyKhz() {
+ return mUplinkFrequency;
}
/**
@@ -173,10 +269,13 @@
return mPhysicalCellId;
}
- /**The radio technology for this physical channel. */
+ /**
+ * @return The network type for this physical channel,
+ * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if unknown.
+ */
@NetworkType
public int getNetworkType() {
- return mRat;
+ return mNetworkType;
}
/**
@@ -186,7 +285,7 @@
* @see #CONNECTION_SECONDARY_SERVING
* @see #CONNECTION_UNKNOWN
*
- * @return Connection status of the cell
+ * @return Connection status of the cell, {@link #CONNECTION_UNKNOWN} if unknown.
*/
@ConnectionStatus
public int getConnectionStatus() {
@@ -210,6 +309,97 @@
}
}
+ private void setDownlinkFrequency() {
+ switch (mNetworkType) {
+ case TelephonyManager.NETWORK_TYPE_NR:
+ mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromNrArfcn(
+ mDownlinkChannelNumber);
+ break;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
+ mBand, mDownlinkChannelNumber, false);
+ break;
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromUarfcn(
+ mBand, mDownlinkChannelNumber, false);
+ break;
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromArfcn(
+ mBand, mDownlinkChannelNumber, false);
+ break;
+ }
+ }
+
+ private void setUplinkFrequency() {
+ switch (mNetworkType){
+ case TelephonyManager.NETWORK_TYPE_NR:
+ mUplinkFrequency = mDownlinkFrequency;
+ break;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ mUplinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
+ mBand, mUplinkChannelNumber, true);
+ break;
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ mUplinkFrequency = AccessNetworkUtils.getFrequencyFromUarfcn(
+ mBand, mUplinkChannelNumber, true);
+ break;
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ mUplinkFrequency = AccessNetworkUtils.getFrequencyFromArfcn(
+ mBand, mUplinkChannelNumber, true);
+ break;
+ }
+ }
+
+ private void setFrequencyRange() {
+ if (mFrequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ return;
+ }
+
+ switch (mNetworkType) {
+ case TelephonyManager.NETWORK_TYPE_NR:
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromNrBand(mBand);
+ break;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromEutranBand(mBand);
+ break;
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromUtranBand(mBand);
+ break;
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromGeranBand(mBand);
+ break;
+ default:
+ mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ break;
+ }
+
+ if (mFrequencyRange == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
+ mFrequencyRange = AccessNetworkUtils.getFrequencyRangeFromArfcn(
+ mDownlinkFrequency);
+ }
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -223,30 +413,37 @@
PhysicalChannelConfig config = (PhysicalChannelConfig) o;
return mCellConnectionStatus == config.mCellConnectionStatus
&& mCellBandwidthDownlinkKhz == config.mCellBandwidthDownlinkKhz
- && mRat == config.mRat
+ && mCellBandwidthUplinkKhz == config.mCellBandwidthUplinkKhz
+ && mNetworkType == config.mNetworkType
&& mFrequencyRange == config.mFrequencyRange
- && mChannelNumber == config.mChannelNumber
+ && mDownlinkChannelNumber == config.mDownlinkChannelNumber
+ && mUplinkChannelNumber == config.mUplinkChannelNumber
&& mPhysicalCellId == config.mPhysicalCellId
- && Arrays.equals(mContextIds, config.mContextIds);
+ && Arrays.equals(mContextIds, config.mContextIds)
+ && mBand == config.mBand
+ && mDownlinkFrequency == config.mDownlinkFrequency
+ && mUplinkFrequency == config.mUplinkFrequency;
}
@Override
public int hashCode() {
return Objects.hash(
- mCellConnectionStatus, mCellBandwidthDownlinkKhz, mRat, mFrequencyRange,
- mChannelNumber, mPhysicalCellId, mContextIds);
+ mCellConnectionStatus, mCellBandwidthDownlinkKhz, mCellBandwidthUplinkKhz,
+ mNetworkType, mFrequencyRange, mDownlinkChannelNumber, mUplinkChannelNumber,
+ mContextIds, mPhysicalCellId, mBand, mDownlinkFrequency, mUplinkFrequency);
}
- public static final @android.annotation.NonNull Parcelable.Creator<PhysicalChannelConfig> CREATOR =
- new Parcelable.Creator<PhysicalChannelConfig>() {
- public PhysicalChannelConfig createFromParcel(Parcel in) {
- return new PhysicalChannelConfig(in);
- }
+ public static final
+ @android.annotation.NonNull Parcelable.Creator<PhysicalChannelConfig> CREATOR =
+ new Parcelable.Creator<PhysicalChannelConfig>() {
+ public PhysicalChannelConfig createFromParcel(Parcel in) {
+ return new PhysicalChannelConfig(in);
+ }
- public PhysicalChannelConfig[] newArray(int size) {
- return new PhysicalChannelConfig[size];
- }
- };
+ public PhysicalChannelConfig[] newArray(int size) {
+ return new PhysicalChannelConfig[size];
+ }
+ };
@Override
public String toString() {
@@ -255,44 +452,64 @@
.append(getConnectionStatusString())
.append(",mCellBandwidthDownlinkKhz=")
.append(mCellBandwidthDownlinkKhz)
- .append(",mRat=")
- .append(TelephonyManager.getNetworkTypeName(mRat))
+ .append(",mCellBandwidthUplinkKhz=")
+ .append(mCellBandwidthUplinkKhz)
+ .append(",mNetworkType=")
+ .append(TelephonyManager.getNetworkTypeName(mNetworkType))
.append(",mFrequencyRange=")
.append(ServiceState.frequencyRangeToString(mFrequencyRange))
- .append(",mChannelNumber=")
- .append(mChannelNumber)
+ .append(",mDownlinkChannelNumber=")
+ .append(mDownlinkChannelNumber)
+ .append(",mUplinkChannelNumber=")
+ .append(mUplinkChannelNumber)
.append(",mContextIds=")
.append(Arrays.toString(mContextIds))
.append(",mPhysicalCellId=")
.append(mPhysicalCellId)
+ .append(",mBand=")
+ .append(mBand)
+ .append(",mDownlinkFrequency=")
+ .append(mDownlinkFrequency)
+ .append(",mUplinkFrequency=")
+ .append(mUplinkFrequency)
.append("}")
.toString();
}
- /** @hide */
- public PhysicalChannelConfig(int status, int bandwidth) {
- mCellConnectionStatus = status;
- mCellBandwidthDownlinkKhz = bandwidth;
- }
-
private PhysicalChannelConfig(Parcel in) {
mCellConnectionStatus = in.readInt();
mCellBandwidthDownlinkKhz = in.readInt();
- mRat = in.readInt();
- mChannelNumber = in.readInt();
+ mCellBandwidthUplinkKhz = in.readInt();
+ mNetworkType = in.readInt();
+ mDownlinkChannelNumber = in.readInt();
+ mUplinkChannelNumber = in.readInt();
mFrequencyRange = in.readInt();
mContextIds = in.createIntArray();
mPhysicalCellId = in.readInt();
+ mBand = in.readInt();
+ if (mBand > BAND_UNKNOWN) {
+ setDownlinkFrequency();
+ setUplinkFrequency();
+ setFrequencyRange();
+ }
}
private PhysicalChannelConfig(Builder builder) {
mCellConnectionStatus = builder.mCellConnectionStatus;
mCellBandwidthDownlinkKhz = builder.mCellBandwidthDownlinkKhz;
- mRat = builder.mRat;
- mChannelNumber = builder.mChannelNumber;
+ mCellBandwidthUplinkKhz = builder.mCellBandwidthUplinkKhz;
+ mNetworkType = builder.mNetworkType;
+ mDownlinkChannelNumber = builder.mDownlinkChannelNumber;
+ mUplinkChannelNumber = builder.mUplinkChannelNumber;
mFrequencyRange = builder.mFrequencyRange;
mContextIds = builder.mContextIds;
mPhysicalCellId = builder.mPhysicalCellId;
+ mBand = builder.mBand;
+ if (mBand > BAND_UNKNOWN) {
+ setDownlinkFrequency();
+ setUplinkFrequency();
+ setFrequencyRange();
+ }
}
/**
@@ -300,61 +517,105 @@
* @hide
*/
public static final class Builder {
- private int mRat;
+ private int mNetworkType;
private int mFrequencyRange;
- private int mChannelNumber;
+ private int mDownlinkChannelNumber;
+ private int mUplinkChannelNumber;
private int mCellBandwidthDownlinkKhz;
+ private int mCellBandwidthUplinkKhz;
private int mCellConnectionStatus;
private int[] mContextIds;
private int mPhysicalCellId;
+ private int mBand;
public Builder() {
- mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
+ mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
- mChannelNumber = CHANNEL_NUMBER_UNKNOWN;
- mCellBandwidthDownlinkKhz = 0;
+ mDownlinkChannelNumber = CHANNEL_NUMBER_UNKNOWN;
+ mUplinkChannelNumber = CHANNEL_NUMBER_UNKNOWN;
+ mCellBandwidthDownlinkKhz = CELL_BANDWIDTH_UNKNOWN;
+ mCellBandwidthUplinkKhz = CELL_BANDWIDTH_UNKNOWN;
mCellConnectionStatus = CONNECTION_UNKNOWN;
mContextIds = new int[0];
mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN;
+ mBand = BAND_UNKNOWN;
}
public PhysicalChannelConfig build() {
return new PhysicalChannelConfig(this);
}
- public Builder setRat(int rat) {
- this.mRat = rat;
+ public @NonNull Builder setNetworkType(@NetworkType int networkType) {
+ if (!TelephonyManager.isNetworkTypeValid(networkType)) {
+ throw new IllegalArgumentException("Network type: " + networkType + " is invalid.");
+ }
+ mNetworkType = networkType;
return this;
}
- public Builder setFrequencyRange(int frequencyRange) {
- this.mFrequencyRange = frequencyRange;
+ public @NonNull Builder setFrequencyRange(int frequencyRange) {
+ if (!ServiceState.isFrequencyRangeValid(frequencyRange)) {
+ throw new IllegalArgumentException("Frequency range: " + frequencyRange +
+ " is invalid.");
+ }
+ mFrequencyRange = frequencyRange;
return this;
}
- public Builder setChannelNumber(int channelNumber) {
- this.mChannelNumber = channelNumber;
+ public @NonNull Builder setDownlinkChannelNumber(int downlinkChannelNumber) {
+ mDownlinkChannelNumber = downlinkChannelNumber;
return this;
}
- public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
- this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
+ public @NonNull Builder setUplinkChannelNumber(int uplinkChannelNumber) {
+ mUplinkChannelNumber = uplinkChannelNumber;
return this;
}
- public Builder setCellConnectionStatus(int connectionStatus) {
- this.mCellConnectionStatus = connectionStatus;
+ public @NonNull Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
+ if (cellBandwidthDownlinkKhz < CELL_BANDWIDTH_UNKNOWN) {
+ throw new IllegalArgumentException("Cell downlink bandwidth(kHz): " +
+ cellBandwidthDownlinkKhz + " is invalid.");
+ }
+ mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
return this;
}
- public Builder setContextIds(int[] contextIds) {
+ public @NonNull Builder setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz) {
+ if (cellBandwidthUplinkKhz < CELL_BANDWIDTH_UNKNOWN) {
+ throw new IllegalArgumentException("Cell uplink bandwidth(kHz): "+
+ cellBandwidthUplinkKhz +" is invalid.");
+ }
+ mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
+ return this;
+ }
+
+ public @NonNull Builder setCellConnectionStatus(int connectionStatus) {
+ mCellConnectionStatus = connectionStatus;
+ return this;
+ }
+
+ public @NonNull Builder setContextIds(int[] contextIds) {
if (contextIds != null) Arrays.sort(contextIds);
- this.mContextIds = contextIds;
+ mContextIds = contextIds;
return this;
}
- public Builder setPhysicalCellId(int physicalCellId) {
- this.mPhysicalCellId = physicalCellId;
+ public @NonNull Builder setPhysicalCellId(int physicalCellId) {
+ if (physicalCellId > PHYSICAL_CELL_ID_MAXIMUM_VALUE) {
+ throw new IllegalArgumentException("Physical cell Id: " + physicalCellId +
+ " is over limit.");
+ }
+ mPhysicalCellId = physicalCellId;
+ return this;
+ }
+
+ public @NonNull Builder setBand(int band) {
+ if (band <= BAND_UNKNOWN) {
+ throw new IllegalArgumentException("Band: " + band +
+ " is invalid.");
+ }
+ mBand = band;
return this;
}
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index dedb1af..f110dae 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -2111,4 +2111,23 @@
}
return false;
}
+
+ /**
+ * The frequency range is valid or not.
+ *
+ * @param frequencyRange The frequency range {@link FrequencyRange}.
+ * @return {@code true} if valid, {@code false} otherwise.
+ *
+ * @hide
+ */
+ public static boolean isFrequencyRangeValid(int frequencyRange) {
+ if (frequencyRange == FREQUENCY_RANGE_LOW
+ || frequencyRange == FREQUENCY_RANGE_MID
+ || frequencyRange == FREQUENCY_RANGE_HIGH
+ || frequencyRange == FREQUENCY_RANGE_MMWAVE) {
+ return true;
+ } else {
+ return false;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/SignalThresholdInfo.java b/telephony/java/android/telephony/SignalThresholdInfo.java
index f6f6d75..bb9c0da3 100644
--- a/telephony/java/android/telephony/SignalThresholdInfo.java
+++ b/telephony/java/android/telephony/SignalThresholdInfo.java
@@ -28,101 +28,109 @@
/**
* Defines the threshold value of the signal strength.
- * @hide
*/
-public class SignalThresholdInfo implements Parcelable {
+public final class SignalThresholdInfo implements Parcelable {
+
+ /**
+ * Unknown signal measurement type.
+ */
+ public static final int SIGNAL_MEASUREMENT_TYPE_UNKNOWN = 0;
+
/**
* Received Signal Strength Indication.
* Range: -113 dBm and -51 dBm
- * Used RAN: GERAN, CDMA2000
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#GERAN},
+ * {@link AccessNetworkConstants.AccessNetworkType#CDMA2000}
* Reference: 3GPP TS 27.007 section 8.5.
*/
- public static final int SIGNAL_RSSI = 1;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSSI = 1;
/**
* Received Signal Code Power.
* Range: -120 dBm to -25 dBm;
- * Used RAN: UTRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#UTRAN}
* Reference: 3GPP TS 25.123, section 9.1.1.1
*/
- public static final int SIGNAL_RSCP = 2;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSCP = 2;
/**
* Reference Signal Received Power.
* Range: -140 dBm to -44 dBm;
- * Used RAN: EUTRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
* Reference: 3GPP TS 36.133 9.1.4
*/
- public static final int SIGNAL_RSRP = 3;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSRP = 3;
/**
* Reference Signal Received Quality
- * Range: -20 dB to -3 dB;
- * Used RAN: EUTRAN
+ * Range: -34 dB to 3 dB;
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
* Reference: 3GPP TS 36.133 9.1.7
*/
- public static final int SIGNAL_RSRQ = 4;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4;
/**
* Reference Signal Signal to Noise Ratio
* Range: -20 dB to 30 dB;
- * Used RAN: EUTRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
*/
- public static final int SIGNAL_RSSNR = 5;
+ public static final int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5;
/**
* 5G SS reference signal received power.
* Range: -140 dBm to -44 dBm.
- * Used RAN: NGRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
* Reference: 3GPP TS 38.215.
*/
- public static final int SIGNAL_SSRSRP = 6;
+ public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6;
/**
* 5G SS reference signal received quality.
- * Range: -20 dB to -3 dB.
- * Used RAN: NGRAN
- * Reference: 3GPP TS 38.215.
+ * Range: -43 dB to 20 dB.
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
+ * Reference: 3GPP TS 38.133 section 10.1.11.1.
*/
- public static final int SIGNAL_SSRSRQ = 7;
+ public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7;
/**
* 5G SS signal-to-noise and interference ratio.
* Range: -23 dB to 40 dB
- * Used RAN: NGRAN
+ * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
* Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
*/
- public static final int SIGNAL_SSSINR = 8;
+ public static final int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8;
/** @hide */
- @IntDef(prefix = { "SIGNAL_" }, value = {
- SIGNAL_RSSI,
- SIGNAL_RSCP,
- SIGNAL_RSRP,
- SIGNAL_RSRQ,
- SIGNAL_RSSNR,
- SIGNAL_SSRSRP,
- SIGNAL_SSRSRQ,
- SIGNAL_SSSINR
+ @IntDef(prefix = {"SIGNAL_MEASUREMENT_TYPE_"}, value = {
+ SIGNAL_MEASUREMENT_TYPE_UNKNOWN,
+ SIGNAL_MEASUREMENT_TYPE_RSSI,
+ SIGNAL_MEASUREMENT_TYPE_RSCP,
+ SIGNAL_MEASUREMENT_TYPE_RSRP,
+ SIGNAL_MEASUREMENT_TYPE_RSRQ,
+ SIGNAL_MEASUREMENT_TYPE_RSSNR,
+ SIGNAL_MEASUREMENT_TYPE_SSRSRP,
+ SIGNAL_MEASUREMENT_TYPE_SSRSRQ,
+ SIGNAL_MEASUREMENT_TYPE_SSSINR
})
@Retention(RetentionPolicy.SOURCE)
- public @interface SignalMeasurementType {}
+ public @interface SignalMeasurementType {
+ }
@SignalMeasurementType
- private int mSignalMeasurement;
+ private final int mSignalMeasurementType;
/**
* A hysteresis time in milliseconds to prevent flapping.
* A value of 0 disables hysteresis
*/
- private int mHysteresisMs;
+ private final int mHysteresisMs;
/**
* An interval in dB defining the required magnitude change between reports.
* hysteresisDb must be smaller than the smallest threshold delta.
* An interval value of 0 disables hysteresis.
*/
- private int mHysteresisDb;
+ private final int mHysteresisDb;
/**
* List of threshold values.
@@ -130,60 +138,340 @@
* The threshold values for which to apply criteria.
* A vector size of 0 disables the use of thresholds for reporting.
*/
- private int[] mThresholds = null;
+ private final int[] mThresholds;
/**
* {@code true} means modem must trigger the report based on the criteria;
* {@code false} means modem must not trigger the report based on the criteria.
*/
- private boolean mIsEnabled = true;
+ private final boolean mIsEnabled;
+
+ /**
+ * The radio access network type associated with the signal thresholds.
+ */
+ @AccessNetworkConstants.RadioAccessNetworkType
+ private final int mRan;
/**
* Indicates the hysteresisMs is disabled.
+ *
+ * @hide
*/
public static final int HYSTERESIS_MS_DISABLED = 0;
/**
* Indicates the hysteresisDb is disabled.
+ *
+ * @hide
*/
public static final int HYSTERESIS_DB_DISABLED = 0;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSI}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSSI_MIN_VALUE = -113;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSI}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSSI_MAX_VALUE = -51;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSCP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSCP_MIN_VALUE = -120;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSCP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSCP_MAX_VALUE = -25;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSRP_MIN_VALUE = -140;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSRP_MAX_VALUE = -44;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRQ}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSRQ_MIN_VALUE = -34;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSRQ}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSRQ_MAX_VALUE = 3;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSNR}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSSNR_MIN_VALUE = -20;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_RSSNR}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_RSSNR_MAX_VALUE = 30;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSRSRP_MIN_VALUE = -140;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRP}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSRSRP_MAX_VALUE = -44;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRQ}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSRSRQ_MIN_VALUE = -43;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSRSRQ}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSRSRQ_MAX_VALUE = 20;
+
+ /**
+ * Minimum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSSINR}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSSINR_MIN_VALUE = -23;
+
+ /**
+ * Maximum valid value for {@link #SIGNAL_MEASUREMENT_TYPE_SSSINR}.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_SSSINR_MAX_VALUE = 40;
+
/**
* Constructor
*
- * @param signalMeasurement Signal Measurement Type
- * @param hysteresisMs hysteresisMs
- * @param hysteresisDb hysteresisDb
- * @param thresholds threshold value
- * @param isEnabled isEnabled
+ * @param ran Radio Access Network type
+ * @param signalMeasurementType Signal Measurement Type
+ * @param hysteresisMs hysteresisMs
+ * @param hysteresisDb hysteresisDb
+ * @param thresholds threshold value
+ * @param isEnabled isEnabled
*/
- public SignalThresholdInfo(@SignalMeasurementType int signalMeasurement,
- int hysteresisMs, int hysteresisDb, @NonNull int [] thresholds, boolean isEnabled) {
- mSignalMeasurement = signalMeasurement;
+ private SignalThresholdInfo(@AccessNetworkConstants.RadioAccessNetworkType int ran,
+ @SignalMeasurementType int signalMeasurementType, int hysteresisMs, int hysteresisDb,
+ @NonNull int[] thresholds, boolean isEnabled) {
+ Objects.requireNonNull(thresholds, "thresholds must not be null");
+ validateRanWithMeasurementType(ran, signalMeasurementType);
+ validateThresholdRange(signalMeasurementType, thresholds);
+
+ mRan = ran;
+ mSignalMeasurementType = signalMeasurementType;
mHysteresisMs = hysteresisMs < 0 ? HYSTERESIS_MS_DISABLED : hysteresisMs;
mHysteresisDb = hysteresisDb < 0 ? HYSTERESIS_DB_DISABLED : hysteresisDb;
- mThresholds = thresholds == null ? null : thresholds.clone();
+ mThresholds = thresholds;
mIsEnabled = isEnabled;
}
- public @SignalMeasurementType int getSignalMeasurement() {
- return mSignalMeasurement;
+ /**
+ * Builder class to create {@link SignalThresholdInfo} objects.
+ */
+ public static final class Builder {
+ private int mRan = AccessNetworkConstants.AccessNetworkType.UNKNOWN;
+ private int mSignalMeasurementType = SIGNAL_MEASUREMENT_TYPE_UNKNOWN;
+ private int mHysteresisMs = HYSTERESIS_MS_DISABLED;
+ private int mHysteresisDb = HYSTERESIS_DB_DISABLED;
+ private int[] mThresholds = null;
+ private boolean mIsEnabled = false;
+
+ /**
+ * Set the radio access network type for the builder instance.
+ *
+ * @param ran The radio access network type
+ * @return the builder to facilitate the chaining
+ */
+ public @NonNull Builder setRadioAccessNetworkType(
+ @AccessNetworkConstants.RadioAccessNetworkType int ran) {
+ mRan = ran;
+ return this;
+ }
+
+ /**
+ * Set the signal measurement type for the builder instance.
+ *
+ * @param signalMeasurementType The signal measurement type
+ * @return the builder to facilitate the chaining
+ */
+ public @NonNull Builder setSignalMeasurementType(
+ @SignalMeasurementType int signalMeasurementType) {
+ mSignalMeasurementType = signalMeasurementType;
+ return this;
+ }
+
+ /**
+ * Set the hysteresis time in milliseconds to prevent flapping. A value of 0 disables
+ * hysteresis.
+ *
+ * @param hysteresisMs the hysteresis time in milliseconds
+ * @return the builder to facilitate the chaining
+ * @hide
+ */
+ public @NonNull Builder setHysteresisMs(int hysteresisMs) {
+ mHysteresisMs = hysteresisMs;
+ return this;
+ }
+
+ /**
+ * Set the interval in dB defining the required magnitude change between reports. A value of
+ * zero disabled dB-based hysteresis restrictions.
+ *
+ * @param hysteresisDb the interval in dB
+ * @return the builder to facilitate the chaining
+ * @hide
+ */
+ public @NonNull Builder setHysteresisDb(int hysteresisDb) {
+ mHysteresisDb = hysteresisDb;
+ return this;
+ }
+
+ /**
+ * Set the signal strength thresholds of the corresponding signal measurement type.
+ *
+ * The range and unit must reference specific SignalMeasurementType.
+ *
+ * @param thresholds array of integer as the signal threshold values
+ * @return the builder to facilitate the chaining
+ *
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSSI
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSCP
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSRP
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSRQ
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSSNR
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRP
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRQ
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSSINR
+ * @see #getThresholds() for more details on signal strength thresholds
+ */
+ public @NonNull Builder setThresholds(@NonNull int[] thresholds) {
+ Objects.requireNonNull(thresholds, "thresholds must not be null");
+ mThresholds = thresholds.clone();
+ Arrays.sort(mThresholds);
+ return this;
+ }
+
+ /**
+ * Set if the modem should trigger the report based on the criteria.
+ *
+ * @param isEnabled true if the modem should trigger the report based on the criteria
+ * @return the builder to facilitate the chaining
+ * @hide
+ */
+ public @NonNull Builder setIsEnabled(boolean isEnabled) {
+ mIsEnabled = isEnabled;
+ return this;
+ }
+
+ /**
+ * Build {@link SignalThresholdInfo} object.
+ *
+ * @return the SignalThresholdInfo object build out
+ *
+ * @throws IllegalArgumentException if the signal measurement type is invalid, any value in
+ * the thresholds is out of range, or the RAN is not allowed to set with the signal
+ * measurement type
+ */
+ public @NonNull SignalThresholdInfo build() {
+ return new SignalThresholdInfo(mRan, mSignalMeasurementType, mHysteresisMs,
+ mHysteresisDb, mThresholds, mIsEnabled);
+ }
}
+ /**
+ * Get the radio access network type.
+ *
+ * @return radio access network type
+ */
+ public @AccessNetworkConstants.RadioAccessNetworkType int getRadioAccessNetworkType() {
+ return mRan;
+ }
+
+ /**
+ * Get the signal measurement type.
+ *
+ * @return the SignalMeasurementType value
+ */
+ public @SignalMeasurementType int getSignalMeasurementType() {
+ return mSignalMeasurementType;
+ }
+
+ /** @hide */
public int getHysteresisMs() {
return mHysteresisMs;
}
+ /** @hide */
public int getHysteresisDb() {
return mHysteresisDb;
}
+ /** @hide */
public boolean isEnabled() {
return mIsEnabled;
}
- public int[] getThresholds() {
- return mThresholds == null ? null : mThresholds.clone();
+ /**
+ * Get the signal strength thresholds.
+ *
+ * Signal strength thresholds are a list of integer used for suggesting signal level and signal
+ * reporting criteria. The range and unit must reference specific SignalMeasurementType.
+ *
+ * Please refer to https://source.android.com/devices/tech/connect/signal-strength on how signal
+ * strength thresholds are used for signal strength reporting.
+ *
+ * @return array of integer of the signal thresholds
+ *
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSSI
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSCP
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSRP
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSRQ
+ * @see #SIGNAL_MEASUREMENT_TYPE_RSSNR
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRP
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRQ
+ * @see #SIGNAL_MEASUREMENT_TYPE_SSSINR
+ */
+ public @NonNull int[] getThresholds() {
+ return mThresholds.clone();
}
@Override
@@ -192,8 +480,9 @@
}
@Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(mSignalMeasurement);
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mRan);
+ out.writeInt(mSignalMeasurementType);
out.writeInt(mHysteresisMs);
out.writeInt(mHysteresisDb);
out.writeIntArray(mThresholds);
@@ -201,7 +490,8 @@
}
private SignalThresholdInfo(Parcel in) {
- mSignalMeasurement = in.readInt();
+ mRan = in.readInt();
+ mSignalMeasurementType = in.readInt();
mHysteresisMs = in.readInt();
mHysteresisDb = in.readInt();
mThresholds = in.createIntArray();
@@ -217,7 +507,8 @@
}
SignalThresholdInfo other = (SignalThresholdInfo) o;
- return mSignalMeasurement == other.mSignalMeasurement
+ return mRan == other.mRan
+ && mSignalMeasurementType == other.mSignalMeasurementType
&& mHysteresisMs == other.mHysteresisMs
&& mHysteresisDb == other.mHysteresisDb
&& Arrays.equals(mThresholds, other.mThresholds)
@@ -226,8 +517,8 @@
@Override
public int hashCode() {
- return Objects.hash(
- mSignalMeasurement, mHysteresisMs, mHysteresisDb, mThresholds, mIsEnabled);
+ return Objects.hash(mRan, mSignalMeasurementType, mHysteresisMs, mHysteresisDb, mThresholds,
+ mIsEnabled);
}
public static final @NonNull Parcelable.Creator<SignalThresholdInfo> CREATOR =
@@ -246,11 +537,83 @@
@Override
public String toString() {
return new StringBuilder("SignalThresholdInfo{")
- .append("mSignalMeasurement=").append(mSignalMeasurement)
- .append("mHysteresisMs=").append(mSignalMeasurement)
- .append("mHysteresisDb=").append(mHysteresisDb)
- .append("mThresholds=").append(Arrays.toString(mThresholds))
- .append("mIsEnabled=").append(mIsEnabled)
- .append("}").toString();
+ .append("mRan=").append(mRan)
+ .append(" mSignalMeasurementType=").append(mSignalMeasurementType)
+ .append(" mHysteresisMs=").append(mHysteresisMs)
+ .append(" mHysteresisDb=").append(mHysteresisDb)
+ .append(" mThresholds=").append(Arrays.toString(mThresholds))
+ .append(" mIsEnabled=").append(mIsEnabled)
+ .append("}").toString();
+ }
+
+ /**
+ * Return true if signal measurement type is valid and the threshold value is in range.
+ */
+ private static boolean isValidThreshold(@SignalMeasurementType int type, int threshold) {
+ switch (type) {
+ case SIGNAL_MEASUREMENT_TYPE_RSSI:
+ return threshold >= SIGNAL_RSSI_MIN_VALUE && threshold <= SIGNAL_RSSI_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_RSCP:
+ return threshold >= SIGNAL_RSCP_MIN_VALUE && threshold <= SIGNAL_RSCP_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_RSRP:
+ return threshold >= SIGNAL_RSRP_MIN_VALUE && threshold <= SIGNAL_RSRP_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_RSRQ:
+ return threshold >= SIGNAL_RSRQ_MIN_VALUE && threshold <= SIGNAL_RSRQ_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_RSSNR:
+ return threshold >= SIGNAL_RSSNR_MIN_VALUE && threshold <= SIGNAL_RSSNR_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_SSRSRP:
+ return threshold >= SIGNAL_SSRSRP_MIN_VALUE && threshold <= SIGNAL_SSRSRP_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_SSRSRQ:
+ return threshold >= SIGNAL_SSRSRQ_MIN_VALUE && threshold <= SIGNAL_SSRSRQ_MAX_VALUE;
+ case SIGNAL_MEASUREMENT_TYPE_SSSINR:
+ return threshold >= SIGNAL_SSSINR_MIN_VALUE && threshold <= SIGNAL_SSSINR_MAX_VALUE;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Return true if the radio access type is allowed to set with the measurement type.
+ */
+ private static boolean isValidRanWithMeasurementType(
+ @AccessNetworkConstants.RadioAccessNetworkType int ran,
+ @SignalMeasurementType int type) {
+ switch (type) {
+ case SIGNAL_MEASUREMENT_TYPE_RSSI:
+ return ran == AccessNetworkConstants.AccessNetworkType.GERAN
+ || ran == AccessNetworkConstants.AccessNetworkType.CDMA2000;
+ case SIGNAL_MEASUREMENT_TYPE_RSCP:
+ return ran == AccessNetworkConstants.AccessNetworkType.UTRAN;
+ case SIGNAL_MEASUREMENT_TYPE_RSRP:
+ case SIGNAL_MEASUREMENT_TYPE_RSRQ:
+ case SIGNAL_MEASUREMENT_TYPE_RSSNR:
+ return ran == AccessNetworkConstants.AccessNetworkType.EUTRAN;
+ case SIGNAL_MEASUREMENT_TYPE_SSRSRP:
+ case SIGNAL_MEASUREMENT_TYPE_SSRSRQ:
+ case SIGNAL_MEASUREMENT_TYPE_SSSINR:
+ return ran == AccessNetworkConstants.AccessNetworkType.NGRAN;
+ default:
+ return false;
+ }
+ }
+
+ private void validateRanWithMeasurementType(
+ @AccessNetworkConstants.RadioAccessNetworkType int ran,
+ @SignalMeasurementType int signalMeasurement) {
+ if (!isValidRanWithMeasurementType(ran, signalMeasurement)) {
+ throw new IllegalArgumentException(
+ "invalid RAN: " + ran + " with signal measurement type: " + signalMeasurement);
+ }
+ }
+
+ private void validateThresholdRange(@SignalMeasurementType int signalMeasurement,
+ int[] thresholds) {
+ for (int threshold : thresholds) {
+ if (!isValidThreshold(signalMeasurement, threshold)) {
+ throw new IllegalArgumentException(
+ "invalid signal measurement type: " + signalMeasurement
+ + " with threshold: " + threshold);
+ }
+ }
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index bfd37cd..2f577a9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -131,10 +131,12 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -564,9 +566,10 @@
/**
* Indicates the maximum size of the call composure picture.
*
- * Pictures sent via {@link #uploadCallComposerPicture(InputStream, Executor, OutcomeReceiver)}
- * or {@link #uploadCallComposerPicture(Path, Executor, OutcomeReceiver)} must not exceed this
- * size, or an error will be returned via the callback in those methods.
+ * Pictures sent via
+ * {@link #uploadCallComposerPicture(InputStream, String, Executor, OutcomeReceiver)}
+ * or {@link #uploadCallComposerPicture(Path, String, Executor, OutcomeReceiver)} must not
+ * exceed this size, or an error will be returned via the callback in those methods.
*
* @return Maximum file size in bytes.
*/
@@ -4310,6 +4313,15 @@
*/
public static final int ERROR_IO_EXCEPTION = 5;
+ /**
+ * Indicates that the device is currently not connected to a network that's capable of
+ * reaching a carrier's RCS servers.
+ *
+ * Clients should prompt the user to remedy the issue by moving to an area with better
+ * signal, by connecting to a different network, or to retry at another time.
+ */
+ public static final int ERROR_NETWORK_UNAVAILABLE = 6;
+
/** @hide */
@IntDef(prefix = {"ERROR_"}, value = {
ERROR_UNKNOWN,
@@ -4318,7 +4330,9 @@
ERROR_AUTHENTICATION_FAILED,
ERROR_INPUT_CLOSED,
ERROR_IO_EXCEPTION,
+ ERROR_NETWORK_UNAVAILABLE,
})
+
@Retention(RetentionPolicy.SOURCE)
public @interface CallComposerError {}
@@ -4355,14 +4369,16 @@
/**
* Uploads a picture to the carrier network for use with call composer.
*
- * @see #uploadCallComposerPicture(InputStream, Executor, OutcomeReceiver)
+ * @see #uploadCallComposerPicture(InputStream, String, Executor, OutcomeReceiver)
* @param pictureToUpload Path to a local file containing the picture to upload.
+ * @param contentType The MIME type of the picture you're uploading (e.g. image/jpeg)
* @param executor The {@link Executor} on which the {@code pictureToUpload} file will be read
* from disk, as well as on which {@code callback} will be called.
* @param callback A callback called when the upload operation terminates, either in success
* or in error.
*/
public void uploadCallComposerPicture(@NonNull Path pictureToUpload,
+ @NonNull String contentType,
@CallbackExecutor @NonNull Executor executor,
@NonNull OutcomeReceiver<ParcelUuid, CallComposerException> callback) {
Objects.requireNonNull(pictureToUpload);
@@ -4390,7 +4406,7 @@
}
InputStream fileStream = Files.newInputStream(pictureToUpload);
try {
- uploadCallComposerPicture(fileStream, executor,
+ uploadCallComposerPicture(fileStream, contentType, executor,
new OutcomeReceiver<ParcelUuid, CallComposerException>() {
@Override
public void onResult(ParcelUuid result) {
@@ -4455,12 +4471,14 @@
* of {@link #getMaximumCallComposerPictureSize()}, the upload will be
* aborted and the callback will be called with an exception containing
* {@link CallComposerException#ERROR_FILE_TOO_LARGE}.
+ * @param contentType The MIME type of the picture you're uploading (e.g. image/jpeg)
* @param executor The {@link Executor} on which the {@code pictureToUpload} stream will be
* read, as well as on which the callback will be called.
* @param callback A callback called when the upload operation terminates, either in success
* or in error.
*/
public void uploadCallComposerPicture(@NonNull InputStream pictureToUpload,
+ @NonNull String contentType,
@CallbackExecutor @NonNull Executor executor,
@NonNull OutcomeReceiver<ParcelUuid, CallComposerException> callback) {
Objects.requireNonNull(pictureToUpload);
@@ -4488,7 +4506,7 @@
try {
telephony.uploadCallComposerPicture(getSubId(), mContext.getOpPackageName(),
- readFd, new ResultReceiver(null) {
+ contentType, readFd, new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle result) {
if (resultCode != CallComposerException.SUCCESS) {
@@ -9029,11 +9047,18 @@
*/
public static final int CALL_COMPOSER_STATUS_ON = 1;
+ /**
+ * Call composer status indicating that sending/receiving pictures is disabled.
+ * All other attachments are still enabled in this state.
+ */
+ public static final int CALL_COMPOSER_STATUS_ON_NO_PICTURES = 2;
+
/** @hide */
@IntDef(prefix = {"CALL_COMPOSER_STATUS_"},
value = {
CALL_COMPOSER_STATUS_ON,
CALL_COMPOSER_STATUS_OFF,
+ CALL_COMPOSER_STATUS_ON_NO_PICTURES,
})
public @interface CallComposerStatus {}
@@ -9041,8 +9066,9 @@
* Set the user-set status for enriched calling with call composer.
*
* @param status user-set status for enriched calling with call composer;
- * it must be a value of either {@link #CALL_COMPOSER_STATUS_ON}
- * or {@link #CALL_COMPOSER_STATUS_OFF}.
+ * it must be any of {@link #CALL_COMPOSER_STATUS_ON}
+ * {@link #CALL_COMPOSER_STATUS_OFF},
+ * or {@link #CALL_COMPOSER_STATUS_ON_NO_PICTURES}
*
* <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
* given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
@@ -9052,7 +9078,8 @@
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setCallComposerStatus(@CallComposerStatus int status) {
- if (status != CALL_COMPOSER_STATUS_ON && status != CALL_COMPOSER_STATUS_OFF) {
+ if (status > CALL_COMPOSER_STATUS_ON_NO_PICTURES
+ || status < CALL_COMPOSER_STATUS_OFF) {
throw new IllegalArgumentException("requested status is invalid");
}
try {
@@ -9074,8 +9101,9 @@
*
* @throws SecurityException if the caller does not have the permission.
*
- * @return the user-set status for enriched calling with call composer either
- * {@link #CALL_COMPOSER_STATUS_ON} or {@link #CALL_COMPOSER_STATUS_OFF}.
+ * @return the user-set status for enriched calling with call composer, any of
+ * {@link #CALL_COMPOSER_STATUS_ON}, {@link #CALL_COMPOSER_STATUS_OFF}, or
+ * {@link #CALL_COMPOSER_STATUS_ON_NO_PICTURES}.
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @CallComposerStatus int getCallComposerStatus() {
@@ -15159,4 +15187,17 @@
e.execute(() -> callback.onAuthenticationFailure(GBA_FAILURE_REASON_FEATURE_NOT_READY));
}
}
+
+ /**
+ * The network type is valid or not.
+ *
+ * @param networkType The network type {@link NetworkType}.
+ * @return {@code true} if valid, {@code false} otherwise.
+ *
+ * @hide
+ */
+ public static boolean isNetworkTypeValid(@NetworkType int networkType) {
+ return networkType >= TelephonyManager.NETWORK_TYPE_UNKNOWN &&
+ networkType <= TelephonyManager.NETWORK_TYPE_NR;
+ }
}
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index ed1f3dd..f48ddb0 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -22,7 +22,6 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.LinkAddress;
-import android.net.LinkProperties;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.DataFailureCause;
@@ -425,7 +424,7 @@
.append(" mtu=").append(getMtu())
.append(" mtuV4=").append(getMtuV4())
.append(" mtuV6=").append(getMtuV6())
- .append(" handoverFailureMode=").append(getHandoverFailureMode())
+ .append(" handoverFailureMode=").append(failureModeToString(mHandoverFailureMode))
.append(" pduSessionId=").append(getPduSessionId())
.append(" defaultQos=").append(mDefaultQos)
.append(" qosSessions=").append(mQosSessions)
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index 52b31d7..a5150b0 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -15,6 +15,7 @@
*/
package android.telephony.euicc;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.PendingIntent;
@@ -102,44 +103,81 @@
this.accessRules = accessRules;
}
- /** @hide */
- @SystemApi
public static final class Builder {
@Nullable private String encodedActivationCode;
@Nullable private String confirmationCode;
@Nullable private String carrierName;
List<UiccAccessRule> accessRules;
+ /** @hide */
+ @SystemApi
public Builder() {}
- public Builder(DownloadableSubscription baseSubscription) {
+ public Builder(@NonNull DownloadableSubscription baseSubscription) {
encodedActivationCode = baseSubscription.getEncodedActivationCode();
confirmationCode = baseSubscription.getConfirmationCode();
carrierName = baseSubscription.getCarrierName();
accessRules = baseSubscription.getAccessRules();
}
+ public Builder(@NonNull String encodedActivationCode) {
+ this.encodedActivationCode = encodedActivationCode;
+ }
+
+ /**
+ * Builds a {@link DownloadableSubscription} object.
+ * @return a non-null {@link DownloadableSubscription} object.
+ */
+ @NonNull
public DownloadableSubscription build() {
return new DownloadableSubscription(encodedActivationCode, confirmationCode,
carrierName, accessRules);
}
- public Builder setEncodedActivationCode(String value) {
+ /**
+ * Sets the encoded activation code.
+ * @param value the activation code to use. An activation code can be parsed from a user
+ * scanned QR code. The format of activation code is defined in SGP.22. For
+ * example, "1$SMDP.GSMA.COM$04386-AGYFT-A74Y8-3F815$1.3.6.1.4.1.31746". For
+ * detail, see {@code com.android.euicc.data.ActivationCode}. Must not be null.
+ */
+ @NonNull
+ public Builder setEncodedActivationCode(@NonNull String value) {
encodedActivationCode = value;
return this;
}
- public Builder setConfirmationCode(String value) {
+ /**
+ * Sets the confirmation code.
+ * @param value the confirmation code to use to authenticate the carrier server got
+ * subscription download.
+ */
+ @NonNull
+ public Builder setConfirmationCode(@NonNull String value) {
confirmationCode = value;
return this;
}
- public Builder setCarrierName(String value) {
+ /**
+ * Sets the user-visible carrier name.
+ * @param value carrier name.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ public Builder setCarrierName(@NonNull String value) {
carrierName = value;
return this;
}
- public Builder setAccessRules(List<UiccAccessRule> value) {
+ /**
+ * Sets the {@link UiccAccessRule}s dictating access to this subscription.
+ * @param value A list of {@link UiccAccessRule}s.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ public Builder setAccessRules(@NonNull List<UiccAccessRule> value) {
accessRules = value;
return this;
}
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
index 66281ed..fd206c1 100644
--- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
@@ -320,4 +320,11 @@
public int hashCode() {
return Objects.hash(mRegisteredTags, mDeregisteringTags, mDeregisteredTags);
}
+
+ @Override
+ public String toString() {
+ return "DelegateRegistrationState{ registered={" + mRegisteredTags
+ + "}, deregistering={" + mDeregisteringTags + "}, deregistered={"
+ + mDeregisteredTags + "}}";
+ }
}
diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java
index 1539224..006cca8 100644
--- a/telephony/java/android/telephony/ims/SipMessage.java
+++ b/telephony/java/android/telephony/ims/SipMessage.java
@@ -22,6 +22,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.telephony.SipMessageParsingUtils;
+
import java.util.Arrays;
import java.util.Objects;
@@ -38,9 +40,6 @@
// Should not be set to true for production!
private static final boolean IS_DEBUGGING = Build.IS_ENG;
- private static final String[] SIP_REQUEST_METHODS = new String[] {"INVITE", "ACK", "OPTIONS",
- "BYE", "CANCEL", "REGISTER"};
-
private final String mStartLine;
private final String mHeaderSection;
private final byte[] mContent;
@@ -72,6 +71,7 @@
mContent = new byte[source.readInt()];
source.readByteArray(mContent);
}
+
/**
* @return The start line of the SIP message, which contains either the request-line or
* status-line.
@@ -128,34 +128,25 @@
} else {
b.append(sanitizeStartLineRequest(mStartLine));
}
- b.append("], [");
- b.append("Header: [");
+ b.append("], Header: [");
if (IS_DEBUGGING) {
b.append(mHeaderSection);
} else {
// only identify transaction id/call ID when it is available.
b.append("***");
}
- b.append("], ");
- b.append("Content: [NOT SHOWN]");
+ b.append("], Content: ");
+ b.append(getContent().length == 0 ? "[NONE]" : "[NOT SHOWN]");
return b.toString();
}
/**
- * Start lines containing requests are formatted: METHOD SP Request-URI SP SIP-Version CRLF.
* Detect if this is a REQUEST and redact Request-URI portion here, as it contains PII.
*/
private String sanitizeStartLineRequest(String startLine) {
+ if (!SipMessageParsingUtils.isSipRequest(startLine)) return startLine;
String[] splitLine = startLine.split(" ");
- if (splitLine == null || splitLine.length == 0) {
- return "(INVALID STARTLINE)";
- }
- for (String method : SIP_REQUEST_METHODS) {
- if (splitLine[0].contains(method)) {
- return splitLine[0] + " <Request-URI> " + splitLine[2];
- }
- }
- return startLine;
+ return splitLine[0] + " <Request-URI> " + splitLine[2];
}
@Override
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
index 522ad81..9d91901 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
@@ -28,6 +28,10 @@
import android.telephony.ims.SipDelegateManager;
import android.telephony.ims.SipMessage;
import android.telephony.ims.stub.SipDelegate;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.SipMessageParsingUtils;
import java.util.ArrayList;
import java.util.Set;
@@ -40,6 +44,7 @@
* @hide
*/
public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMessageCallback {
+ private static final String LOG_TAG = "SipDelegateAW";
private final ISipDelegate.Stub mDelegateBinder = new ISipDelegate.Stub() {
@Override
@@ -183,11 +188,15 @@
}
private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) {
- //TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage
- // transaction ID can not be parsed.
+ String transactionId = SipMessageParsingUtils.getTransactionId(m.getHeaderSection());
+ if (TextUtils.isEmpty(transactionId)) {
+ Log.w(LOG_TAG, "failure to parse SipMessage.");
+ throw new IllegalArgumentException("Malformed SipMessage, can not determine "
+ + "transaction ID.");
+ }
SipDelegate d = mDelegate;
if (d != null) {
- mExecutor.execute(() -> d.notifyMessageReceiveError(null, reason));
+ mExecutor.execute(() -> d.notifyMessageReceiveError(transactionId, reason));
}
}
}
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
index a35039b..c877aca 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
@@ -28,9 +28,12 @@
import android.telephony.ims.stub.DelegateConnectionMessageCallback;
import android.telephony.ims.stub.DelegateConnectionStateCallback;
import android.telephony.ims.stub.SipDelegate;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.telephony.SipMessageParsingUtils;
+
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.Executor;
@@ -265,9 +268,13 @@
}
private void notifyLocalMessageFailedToSend(SipMessage m, int reason) {
- //TODO: parse transaction ID or throw IllegalArgumentException if the SipMessage
- // transaction ID can not be parsed.
+ String transactionId = SipMessageParsingUtils.getTransactionId(m.getHeaderSection());
+ if (TextUtils.isEmpty(transactionId)) {
+ Log.w(LOG_TAG, "sendMessage detected a malformed SipMessage and can not get a "
+ + "transaction ID.");
+ throw new IllegalArgumentException("Could not send SipMessage due to malformed header");
+ }
mExecutor.execute(() ->
- mMessageCallback.onMessageSendFailure(null, reason));
+ mMessageCallback.onMessageSendFailure(transactionId, reason));
}
}
diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
index d2cb976..d9734a7 100644
--- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
+++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
@@ -18,15 +18,12 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.net.Uri;
import android.telephony.ims.ImsException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
-import java.util.List;
-
/**
* The interface of the capabilities event listener for ImsService to notify the framework of the
* UCE request and status updated.
@@ -84,25 +81,4 @@
* Telephony stack has crashed.
*/
void onUnpublish() throws ImsException;
-
- /**
- * Inform the framework of a query for this device's UCE capabilities.
- * <p>
- * The framework will respond via the
- * {@link OptionsRequestCallback#onRespondToCapabilityRequest} or
- * {@link OptionsRequestCallback#onRespondToCapabilityRequestWithError}
- * @param contactUri The URI associated with the remote contact that is
- * requesting capabilities.
- * @param remoteCapabilities The remote contact's capability information.
- * @param callback The callback of this request which is sent from the remote user.
- * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not
- * currently connected to the framework. This can happen if the {@link RcsFeature} is not
- * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
- * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
- * cases when the Telephony stack has crashed.
- * @hide
- */
- void onRemoteCapabilityRequest(@NonNull Uri contactUri,
- @NonNull List<String> remoteCapabilities,
- @NonNull OptionsRequestCallback callback) throws ImsException;
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 1a8b08b..46c9dde 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -629,7 +629,7 @@
* successful iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
*/
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
boolean iccCloseLogicalChannel(int subId, int channel);
/**
@@ -671,7 +671,7 @@
* @return The APDU response from the ICC card with the status appended at
* the end.
*/
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
+ @UnsupportedAppUsage(trackingBug = 171933273)
String iccTransmitApduLogicalChannel(int subId, int channel, int cla, int instruction,
int p1, int p2, int p3, String data);
@@ -1262,7 +1262,7 @@
int getRadioAccessFamily(in int phoneId, String callingPackage);
void uploadCallComposerPicture(int subscriptionId, String callingPackage,
- in ParcelFileDescriptor fd, in ResultReceiver callback);
+ String contentType, in ParcelFileDescriptor fd, in ResultReceiver callback);
/**
* Enables or disables video calling.
diff --git a/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java b/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
index fc1d47b..65b4bd0 100644
--- a/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
+++ b/tests/AccessoryDisplay/sink/src/com/android/accessorydisplay/sink/SinkActivity.java
@@ -167,7 +167,7 @@
Intent intent = new Intent(ACTION_USB_DEVICE_PERMISSION);
intent.setPackage(getPackageName());
PendingIntent pendingIntent = PendingIntent.getBroadcast(
- this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+ this, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE);
mUsbManager.requestPermission(device, pendingIntent);
return;
}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 768cfae..a8e47b5 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -100,7 +100,7 @@
Intent intent = new Intent(ActivityTestMain.this, AlarmSpamReceiver.class);
intent.setAction("com.example.SPAM_ALARM=" + when);
PendingIntent pi = PendingIntent.getBroadcast(ActivityTestMain.this,
- 0, intent, 0);
+ 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
mAlarm.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, when+(30*1000), pi);
scheduleSpamAlarm(30*1000);
} break;
@@ -134,7 +134,7 @@
// Also send a broadcast alarm to evaluate the alarm fast-forward policy
intent.putExtra(SLOW_RECEIVER_EXTRA, 4);
- PendingIntent pi = PendingIntent.getBroadcast(ActivityTestMain.this, 1, intent, 0);
+ PendingIntent pi = PendingIntent.getBroadcast(ActivityTestMain.this, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long now = SystemClock.elapsedRealtime();
Log.i(TAG, "Setting alarm for now + 5 seconds");
@@ -493,7 +493,7 @@
Intent receiveIntent = new Intent(ActivityTestMain.this, TrackTimeReceiver.class);
receiveIntent.putExtra("something", "yeah, this is us!");
options.requestUsageTimeReport(PendingIntent.getBroadcast(ActivityTestMain.this,
- 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT));
+ 0, receiveIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED));
startActivity(Intent.createChooser(intent, "Who do you love?"), options.toBundle());
return true;
}
diff --git a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
index fa292bd..6985702 100644
--- a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
+++ b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
@@ -83,7 +83,7 @@
filter.addAction(intent.getAction());
registerReceiver(mAlarmReceiver, filter);
mAlarmIntent = PendingIntent.getBroadcast(this, 0, intent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
setDozeScreenState(DISPLAY_STATE_WHEN_DOZING);
}
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
index d4cbbf9..11a26d6 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
@@ -41,7 +41,7 @@
new Intent(this, FrameworkPerfActivity.class)
.setAction(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
- .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_MUTABLE_UNAUDITED))
.setOngoing(true)
.build();
startForeground(1, status);
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 9a2def9..1a940c7 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -1016,6 +1016,15 @@
</intent-filter>
</activity>
+ <activity android:name="RippleActivity"
+ android:label="Animation/Ripple Animation"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="com.android.test.hwui.TEST"/>
+ </intent-filter>
+ </activity>
+
<activity android:name="MultiProducerActivity"
android:label="Threads/Multiple Producers"
android:exported="true">
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
index b53b78a..8be3b7e 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
@@ -35,9 +35,6 @@
import android.os.Bundle;
import android.view.View;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
@SuppressWarnings({"UnusedDeclaration"})
public class ColorFiltersMutateActivity extends Activity {
@Override
@@ -54,11 +51,13 @@
private final Paint mLightingPaint;
private final Paint mBlendPaint;
private final Paint mShaderPaint;
+ private final RuntimeShader mRuntimeShader;
private float mSaturation = 0.0f;
private int mLightAdd = 0;
private int mLightMul = 0;
private int mPorterDuffColor = 0;
+ private float mShaderParam1 = 0.0f;
static final String sSkSL =
"in shader bitmapShader;\n"
@@ -67,8 +66,6 @@
+ " return half4(sample(bitmapShader, xy).rgb, param1);\n"
+ "}\n";
- private byte[] mUniforms = new byte[4];
-
BitmapsView(Context c) {
super(c);
@@ -86,11 +83,13 @@
mBlendPaint = new Paint();
mBlendPaint.setColorFilter(new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_OVER));
+ mRuntimeShader = new RuntimeShader(sSkSL, false);
+ mRuntimeShader.setUniform("param1", mShaderParam1);
+ mRuntimeShader.setInputShader("bitmapShader", new BitmapShader(mBitmap1,
+ Shader.TileMode.CLAMP,
+ Shader.TileMode.CLAMP));
mShaderPaint = new Paint();
- Shader[] inputShaders = { new BitmapShader(mBitmap1, Shader.TileMode.CLAMP,
- Shader.TileMode.CLAMP) };
- mShaderPaint.setShader(new RuntimeShader(sSkSL, mUniforms, inputShaders, true));
- setShaderParam1(0.0f);
+ mShaderPaint.setShader(mRuntimeShader);
ObjectAnimator sat = ObjectAnimator.ofFloat(this, "saturation", 1.0f);
sat.setDuration(1000);
@@ -177,20 +176,15 @@
}
public void setShaderParam1(float value) {
- RuntimeShader shader = (RuntimeShader) mShaderPaint.getShader();
- ByteBuffer buffer = ByteBuffer.wrap(mUniforms);
- buffer.order(ByteOrder.LITTLE_ENDIAN);
- buffer.putFloat(value);
- shader.updateUniforms(mUniforms);
+ mShaderParam1 = value;
+ mRuntimeShader.setUniform("param1", mShaderParam1);
invalidate();
}
// If either valueFrom or valueTo is null, then a getter function will also be derived
// and called by the animator class.
public float getShaderParam1() {
- ByteBuffer buffer = ByteBuffer.wrap(mUniforms);
- buffer.order(ByteOrder.LITTLE_ENDIAN);
- return buffer.getFloat();
+ return mShaderParam1;
}
@Override
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
new file mode 100644
index 0000000..f6d9a73
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RuntimeShader;
+import android.os.Bundle;
+import android.os.Trace;
+import android.view.RenderNodeAnimator;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+
+import java.util.ArrayList;
+
+public class RippleActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.addView(new RippleView(this),
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+ setContentView(layout);
+ }
+
+ static class RippleView extends View {
+ static final int DURATION = 1000;
+ static final int MAX_RADIUS = 250;
+
+ private boolean mToggle = false;
+ ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>();
+
+ CanvasProperty<Float> mX;
+ CanvasProperty<Float> mY;
+ CanvasProperty<Float> mRadius;
+ CanvasProperty<Float> mProgress;
+ CanvasProperty<Paint> mPaint;
+ RuntimeShader mRuntimeShader;
+
+ static final String sSkSL = ""
+ + "uniform float2 in_origin;"
+ + "uniform float in_progress;\n"
+ + "uniform float in_maxRadius;\n"
+ + "uniform shader in_paintColor;\n"
+ + "float dist2(float2 p0, float2 pf) { return sqrt((pf.x - p0.x) * (pf.x - p0.x) + "
+ + "(pf.y - p0.y) * (pf.y - p0.y)); }\n"
+ + "float mod2(float a, float b) { return a - (b * floor(a / b)); }\n"
+ + "float rand(float2 src) { return fract(sin(dot(src.xy, float2(12.9898, 78.233)))"
+ + " * 43758.5453123); }\n"
+ + "float4 main(float2 p)\n"
+ + "{\n"
+ + " float fraction = in_progress;\n"
+ + " float2 fragCoord = p;//sk_FragCoord.xy;\n"
+ + " float maxDist = in_maxRadius;\n"
+ + " float fragDist = dist2(in_origin, fragCoord.xy);\n"
+ + " float circleRadius = maxDist * fraction;\n"
+ + " float colorVal = (fragDist - circleRadius) / maxDist;\n"
+ + " float d = fragDist < circleRadius \n"
+ + " ? 1. - abs(colorVal * 2. * smoothstep(0., 1., fraction)) \n"
+ + " : 1. - abs(colorVal * 3.);\n"
+ + " d = smoothstep(0., 1., d);\n"
+ + " float divider = 2.;\n"
+ + " float x = floor(fragCoord.x / divider);\n"
+ + " float y = floor(fragCoord.y / divider);\n"
+ + " float density = .95;\n"
+ + " d = rand(float2(x, y)) > density ? d : d * .2;\n"
+ + " d = d * rand(float2(fraction, x * y));\n"
+ + " float alpha = 1. - pow(fraction, 3.);\n"
+ + " return float4(sample(in_paintColor).rgb, d * alpha);\n"
+ + "}";
+
+ RippleView(Context c) {
+ super(c);
+ setClickable(true);
+
+ mX = CanvasProperty.createFloat(200.0f);
+ mY = CanvasProperty.createFloat(200.0f);
+ mRadius = CanvasProperty.createFloat(150.0f);
+ mProgress = CanvasProperty.createFloat(0.0f);
+
+ Paint p = new Paint();
+ p.setAntiAlias(true);
+ p.setColor(0xFFFF0000);
+ mPaint = CanvasProperty.createPaint(p);
+
+ mRuntimeShader = new RuntimeShader(sSkSL, false);
+ mRuntimeShader.setUniform("in_maxRadius", MAX_RADIUS);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (canvas.isHardwareAccelerated()) {
+ RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ recordingCanvas.drawRipple(mX, mY, mRadius, mPaint, mProgress, mRuntimeShader);
+ }
+ }
+
+ @Override
+ public boolean performClick() {
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ mRunningAnimations.get(i).cancel();
+ }
+ mRunningAnimations.clear();
+
+ mToggle = !mToggle;
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mX, mToggle ? 400.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mY, mToggle ? 600.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mRadius, mToggle ? MAX_RADIUS : 150.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mProgress, mToggle ? 1.0f : 0.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_ALPHA, 64.0f));
+
+ // Will be "chained" to run after the above
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_ALPHA, 255.0f));
+
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ RenderNodeAnimator anim = mRunningAnimations.get(i);
+ anim.setDuration(DURATION);
+ anim.setTarget(this);
+ if (i == (mRunningAnimations.size() - 1)) {
+ // "chain" test
+ anim.setStartValue(64.0f);
+ anim.setStartDelay(anim.getDuration());
+ }
+ anim.start();
+ }
+
+ if (mToggle) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "pretendBusy");
+ try {
+ Thread.sleep(DURATION);
+ } catch (InterruptedException e) {
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ });
+ }
+ return true;
+ }
+ }
+}
diff --git a/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java b/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
index ceb0937..6483c92 100644
--- a/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
+++ b/tests/OneMedia/src/com/android/onemedia/NotificationHelper.java
@@ -52,22 +52,22 @@
mIntents.put(R.drawable.ic_pause, PendingIntent.getBroadcast(mService, 100, new Intent(
com.android.onemedia.playback.RequestUtils.ACTION_PAUSE).setPackage(pkg),
- PendingIntent.FLAG_CANCEL_CURRENT));
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED));
mIntents.put(R.drawable.ic_play_arrow, PendingIntent.getBroadcast(mService, 100,
new Intent(com.android.onemedia.playback.RequestUtils.ACTION_PLAY).setPackage(pkg),
- PendingIntent.FLAG_CANCEL_CURRENT));
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED));
mIntents.put(R.drawable.ic_skip_previous, PendingIntent.getBroadcast(mService, 100,
new Intent(com.android.onemedia.playback.RequestUtils.ACTION_PREV).setPackage(pkg),
- PendingIntent.FLAG_CANCEL_CURRENT));
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED));
mIntents.put(R.drawable.ic_skip_next, PendingIntent.getBroadcast(mService, 100,
new Intent(com.android.onemedia.playback.RequestUtils.ACTION_NEXT).setPackage(pkg),
- PendingIntent.FLAG_CANCEL_CURRENT));
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED));
mIntents.put(R.drawable.ic_fast_rewind, PendingIntent.getBroadcast(mService, 100,
new Intent(com.android.onemedia.playback.RequestUtils.ACTION_REW).setPackage(pkg),
- PendingIntent.FLAG_CANCEL_CURRENT));
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED));
mIntents.put(R.drawable.ic_fast_forward, PendingIntent.getBroadcast(mService, 100,
new Intent(com.android.onemedia.playback.RequestUtils.ACTION_FFWD).setPackage(pkg),
- PendingIntent.FLAG_CANCEL_CURRENT));
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED));
}
/**
diff --git a/tests/StagedInstallTest/OWNERS b/tests/StagedInstallTest/OWNERS
index d825dfd..aac68e9 100644
--- a/tests/StagedInstallTest/OWNERS
+++ b/tests/StagedInstallTest/OWNERS
@@ -1 +1,5 @@
include /services/core/java/com/android/server/pm/OWNERS
+
+dariofreni@google.com
+ioffe@google.com
+olilan@google.com
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index 9862116..601688e 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -497,7 +497,7 @@
intent.setData(Uri.fromParts("content", "//status_bar_test/delete/" + id, null));
intent.putExtra(ConfirmationActivity.EXTRA_TITLE, "Delete intent");
intent.putExtra(ConfirmationActivity.EXTRA_TEXT, "id: " + id);
- return PendingIntent.getActivity(this, 0, intent, 0);
+ return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
}
private PendingIntent makeContentIntent(int id) {
@@ -505,7 +505,7 @@
intent.setData(Uri.fromParts("content", "//status_bar_test/content/" + id, null));
intent.putExtra(ConfirmationActivity.EXTRA_TITLE, "Content intent");
intent.putExtra(ConfirmationActivity.EXTRA_TEXT, "id: " + id);
- return PendingIntent.getActivity(this, 0, intent, 0);
+ return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
}
}
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 163250d..429e676 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -1160,12 +1160,12 @@
private PendingIntent makeIntent() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
- return PendingIntent.getActivity(this, 0, intent, 0);
+ return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
}
private PendingIntent makeIntent2() {
Intent intent = new Intent(this, StatusBarTest.class);
- return PendingIntent.getActivity(this, 0, intent, 0);
+ return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
}
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index 3d72ee6..6bcfebc 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -160,7 +160,7 @@
StatusBarTest.this,
0,
fullScreenIntent,
- PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
Notification not = new Notification.Builder(StatusBarTest.this)
.setSmallIcon(R.drawable.stat_sys_phone)
.setWhen(System.currentTimeMillis() - (1000 * 60 * 60 * 24))
diff --git a/tests/SurfaceViewBufferTests/OWNERS b/tests/SurfaceViewBufferTests/OWNERS
new file mode 100644
index 0000000..d50528c
--- /dev/null
+++ b/tests/SurfaceViewBufferTests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
index eb16bad..7d278dc 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
@@ -27,12 +27,13 @@
@Test
fun testQueueBuffers() {
val numFrames = 100L
- val trace = withTrace {
+ val trace = withTrace { activity ->
for (i in 1..numFrames) {
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ activity.mSurfaceProxy.ANativeWindowLock()
+ activity.mSurfaceProxy.ANativeWindowUnlockAndPost()
}
- assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(numFrames, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.waitUntilBufferDisplayed(numFrames,
+ 1000 /* ms */))
}
assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
@@ -40,13 +41,13 @@
@Test
fun testSetBufferScalingMode_outOfOrderQueueBuffer() {
- val trace = withTrace {
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ val trace = withTrace { activity ->
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
- it.mSurfaceProxy.SurfaceQueueBuffer(1)
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
- assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(2, 5000 /* ms */))
+ activity.mSurfaceProxy.SurfaceQueueBuffer(1)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ assertEquals(0, activity.mSurfaceProxy.waitUntilBufferDisplayed(2, 5000 /* ms */))
}
assertThat(trace).hasFrameSequence("SurfaceView", 1..2L)
@@ -55,15 +56,16 @@
@Test
fun testSetBufferScalingMode_multipleDequeueBuffer() {
val numFrames = 20L
- val trace = withTrace {
+ val trace = withTrace { activity ->
for (count in 1..(numFrames / 2)) {
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
- it.mSurfaceProxy.SurfaceQueueBuffer(1)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(1)
}
- assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(numFrames, 5000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.waitUntilBufferDisplayed(numFrames,
+ 5000 /* ms */))
}
assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
@@ -73,19 +75,20 @@
fun testSetBufferCount_queueMaxBufferCountMinusOne() {
val numBufferCount = 8
val numFrames = numBufferCount * 5L
- val trace = withTrace {
- assertEquals(0, it.mSurfaceProxy.NativeWindowSetBufferCount(numBufferCount + 1))
+ val trace = withTrace { activity ->
+ assertEquals(0, activity.mSurfaceProxy.NativeWindowSetBufferCount(numBufferCount + 1))
for (i in 1..numFrames / numBufferCount) {
for (bufferSlot in 0..numBufferCount - 1) {
assertEquals(0,
- it.mSurfaceProxy.SurfaceDequeueBuffer(bufferSlot, 1000 /* ms */))
+ activity.mSurfaceProxy.SurfaceDequeueBuffer(bufferSlot, 1000 /* ms */))
}
for (bufferSlot in 0..numBufferCount - 1) {
- it.mSurfaceProxy.SurfaceQueueBuffer(bufferSlot)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(bufferSlot)
}
}
- assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(numFrames, 5000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.waitUntilBufferDisplayed(numFrames,
+ 5000 /* ms */))
}
assertThat(trace).hasFrameSequence("SurfaceView", 1..numFrames)
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
index 95a7fd5..e9e0246 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
@@ -28,20 +28,21 @@
class BufferRejectionTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(useBlastAdapter) {
@Test
fun testSetBuffersGeometry_0x0_rejectsBuffer() {
- val trace = withTrace {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 100, 100,
+ val trace = withTrace { activity ->
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, 100, 100,
R8G8B8A8_UNORM)
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 0, 0, R8G8B8A8_UNORM)
+ activity.mSurfaceProxy.ANativeWindowLock()
+ activity.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ activity.mSurfaceProxy.ANativeWindowLock()
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, 0, 0,
+ R8G8B8A8_UNORM)
// Submit buffer one with a different size which should be rejected
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ activity.mSurfaceProxy.ANativeWindowUnlockAndPost()
// submit a buffer with the default buffer size
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
- it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */)
+ activity.mSurfaceProxy.ANativeWindowLock()
+ activity.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ activity.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */)
}
// Verify we reject buffers since scaling mode == NATIVE_WINDOW_SCALING_MODE_FREEZE
assertThat(trace).layer("SurfaceView", 2).doesNotExist()
@@ -61,22 +62,22 @@
@Test
fun testSetBufferScalingMode_freeze() {
val bufferSize = Point(300, 200)
- val trace = withTrace {
- it.drawFrame()
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ val trace = withTrace { activity ->
+ activity.drawFrame()
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, bufferSize,
R8G8B8A8_UNORM)
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
// Change buffer size and set scaling mode to freeze
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, Point(0, 0),
R8G8B8A8_UNORM)
// first dequeued buffer does not have the new size so it should be rejected.
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
- it.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
- it.mSurfaceProxy.SurfaceQueueBuffer(1)
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
}
// verify buffer size is reset to default buffer size
@@ -88,23 +89,23 @@
@Test
fun testSetBufferScalingMode_freeze_withBufferRotation() {
val rotatedBufferSize = Point(defaultBufferSize.y, defaultBufferSize.x)
- val trace = withTrace {
- it.drawFrame()
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, rotatedBufferSize,
- R8G8B8A8_UNORM)
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ val trace = withTrace { activity ->
+ activity.drawFrame()
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!,
+ rotatedBufferSize, R8G8B8A8_UNORM)
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
// Change buffer size and set scaling mode to freeze
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, Point(0, 0),
R8G8B8A8_UNORM)
// first dequeued buffer does not have the new size so it should be rejected.
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
// add a buffer transform so the buffer size is correct.
- it.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.ROT_90)
- it.mSurfaceProxy.SurfaceQueueBuffer(1)
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.ROT_90)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
}
// verify buffer size is reset to default buffer size
@@ -117,24 +118,24 @@
@Test
fun testRejectedBuffersAreReleased() {
val bufferSize = Point(300, 200)
- val trace = withTrace {
+ val trace = withTrace { activity ->
for (count in 0 until 5) {
- it.drawFrame()
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed((count * 3) + 1L,
+ activity.drawFrame()
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed((count * 3) + 1L,
500 /* ms */), 0)
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
- R8G8B8A8_UNORM)
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!,
+ bufferSize, R8G8B8A8_UNORM)
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
// Change buffer size and set scaling mode to freeze
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
- R8G8B8A8_UNORM)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!,
+ Point(0, 0), R8G8B8A8_UNORM)
// first dequeued buffer does not have the new size so it should be rejected.
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
- it.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
- it.mSurfaceProxy.SurfaceQueueBuffer(1)
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed((count * 3) + 3L,
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed((count * 3) + 3L,
500 /* ms */), 0)
}
}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
index 03f8c05..0802990 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
@@ -15,25 +15,31 @@
*/
package com.android.test
+import android.graphics.Color
import android.graphics.Point
+import android.graphics.Rect
+import android.os.SystemClock
import com.android.server.wm.flicker.traces.layers.LayersTraceSubject.Companion.assertThat
import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
@RunWith(Parameterized::class)
class GeometryTests(useBlastAdapter: Boolean) : SurfaceTracingTestBase(useBlastAdapter) {
@Test
fun testSetBuffersGeometry_0x0_resetsBufferSize() {
- val trace = withTrace {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, 0, 0,
+ val trace = withTrace { activity ->
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, 0, 0,
R8G8B8A8_UNORM)
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
- it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
+ activity.mSurfaceProxy.ANativeWindowLock()
+ activity.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
}
// verify buffer size is reset to default buffer size
@@ -43,11 +49,11 @@
@Test
fun testSetBuffersGeometry_smallerThanBuffer() {
val bufferSize = Point(300, 200)
- val trace = withTrace {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ val trace = withTrace { activity ->
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, bufferSize,
R8G8B8A8_UNORM)
- it.drawFrame()
- it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
+ activity.drawFrame()
+ activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
}
assertThat(trace).layer("SurfaceView", 1).also {
@@ -60,11 +66,11 @@
@Test
fun testSetBuffersGeometry_largerThanBuffer() {
val bufferSize = Point(3000, 2000)
- val trace = withTrace {
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ val trace = withTrace { activity ->
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, bufferSize,
R8G8B8A8_UNORM)
- it.drawFrame()
- it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
+ activity.drawFrame()
+ activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
}
assertThat(trace).layer("SurfaceView", 1).also {
@@ -77,22 +83,22 @@
@Test
fun testSetBufferScalingMode_freeze() {
val bufferSize = Point(300, 200)
- val trace = withTrace {
- it.drawFrame()
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, bufferSize,
+ val trace = withTrace { activity ->
+ activity.drawFrame()
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, bufferSize,
R8G8B8A8_UNORM)
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
// Change buffer size and set scaling mode to freeze
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, Point(0, 0),
R8G8B8A8_UNORM)
// first dequeued buffer does not have the new size so it should be rejected.
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
- it.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
- it.mSurfaceProxy.SurfaceQueueBuffer(1)
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
}
// verify buffer size is reset to default buffer size
@@ -105,11 +111,11 @@
fun testSetBuffersTransform_FLIP() {
val transforms = arrayOf(Transform.FLIP_H, Transform.FLIP_V, Transform.ROT_180).withIndex()
for ((index, transform) in transforms) {
- val trace = withTrace {
- it.mSurfaceProxy.ANativeWindowSetBuffersTransform(transform)
- it.mSurfaceProxy.ANativeWindowLock()
- it.mSurfaceProxy.ANativeWindowUnlockAndPost()
- it.mSurfaceProxy.waitUntilBufferDisplayed(index + 1L, 500 /* ms */)
+ val trace = withTrace { activity ->
+ activity.mSurfaceProxy.ANativeWindowSetBuffersTransform(transform)
+ activity.mSurfaceProxy.ANativeWindowLock()
+ activity.mSurfaceProxy.ANativeWindowUnlockAndPost()
+ activity.mSurfaceProxy.waitUntilBufferDisplayed(index + 1L, 500 /* ms */)
}
assertThat(trace).layer("SurfaceView", index + 1L).also {
@@ -119,4 +125,100 @@
}
}
}
+
+ @Test
+ fun testSurfaceViewResizeImmediatelyWithNonFreezeScaling() {
+ val surfaceViewPosition = Rect()
+ var trace = withTrace { activity ->
+ activity.mSurfaceProxy.SurfaceSetScalingMode(ScalingMode.SCALE_TO_WINDOW)
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
+ activity.mSurfaceProxy.drawBuffer(0, Color.BLUE)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
+ activity.mSurfaceView!!.getBoundsOnScreen(surfaceViewPosition)
+ }
+
+ runOnUiThread {
+ val svBounds = Rect(0, 0, defaultBufferSize.x, defaultBufferSize.y)
+ svBounds.offsetTo(surfaceViewPosition.left, surfaceViewPosition.top)
+ checkPixels(svBounds, Color.BLUE)
+ }
+
+ // check that the layer and buffer starts with the default size
+ assertThat(trace).layer("SurfaceView", 1).also {
+ it.hasBufferSize(defaultBufferSize)
+ it.hasLayerSize(defaultBufferSize)
+ }
+ val newSize = Point(1280, 960)
+ lateinit var resizeCountDownLatch: CountDownLatch
+ runOnUiThread {
+ resizeCountDownLatch = it.resizeSurfaceView(newSize)
+ }
+ assertTrue(resizeCountDownLatch.await(1000, TimeUnit.MILLISECONDS))
+ // wait for sf to handle the resize transaction request
+ SystemClock.sleep(500)
+ trace = withTrace { _ ->
+ // take a trace with the new size
+ }
+
+ // check that the layer size has changed and the buffer is now streched to the new layer
+ // size
+ runOnUiThread {
+ val svBounds = Rect(0, 0, newSize.x, newSize.y)
+ svBounds.offsetTo(surfaceViewPosition.left, surfaceViewPosition.top)
+ checkPixels(svBounds, Color.BLUE)
+ }
+
+ assertThat(trace).layer("SurfaceView", 1).also {
+ it.hasLayerSize(newSize)
+ it.hasBufferSize(defaultBufferSize)
+ }
+ }
+
+ @Test
+ fun testSurfaceViewDoesNotResizeWithDefaultScaling() {
+ val surfaceViewPosition = Rect()
+ var trace = withTrace { activity ->
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
+ activity.mSurfaceProxy.drawBuffer(0, Color.BLUE)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */)
+ activity.mSurfaceView!!.getBoundsOnScreen(surfaceViewPosition)
+ }
+
+ runOnUiThread {
+ val svBounds = Rect(0, 0, defaultBufferSize.x, defaultBufferSize.y)
+ svBounds.offsetTo(surfaceViewPosition.left, surfaceViewPosition.top)
+ checkPixels(svBounds, Color.BLUE)
+ }
+
+ // check that the layer and buffer starts with the default size
+ assertThat(trace).layer("SurfaceView", 1).also {
+ it.hasBufferSize(defaultBufferSize)
+ it.hasLayerSize(defaultBufferSize)
+ }
+ val newSize = Point(1280, 960)
+ lateinit var resizeCountDownLatch: CountDownLatch
+ runOnUiThread {
+ resizeCountDownLatch = it.resizeSurfaceView(newSize)
+ }
+ assertTrue(resizeCountDownLatch.await(1000, TimeUnit.MILLISECONDS))
+ // wait for sf to handle the resize transaction request
+ SystemClock.sleep(500)
+ trace = withTrace { _ ->
+ // take a trace after the size change
+ }
+
+ // check the layer and buffer remains the same size
+ runOnUiThread {
+ val svBounds = Rect(0, 0, defaultBufferSize.x, defaultBufferSize.y)
+ svBounds.offsetTo(surfaceViewPosition.left, surfaceViewPosition.top)
+ checkPixels(svBounds, Color.BLUE)
+ }
+
+ assertThat(trace).layer("SurfaceView", 1).also {
+ it.hasLayerSize(defaultBufferSize)
+ it.hasBufferSize(defaultBufferSize)
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
index eac3041..69012bd 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
@@ -44,28 +44,28 @@
"fixed scaling mode.", useBlastAdapter)
val rotatedBufferSize = Point(defaultBufferSize.y, defaultBufferSize.x)
- val trace = withTrace {
+ val trace = withTrace { activity ->
// Inverse display transforms are sticky AND they are only consumed by the sf after
// a valid buffer has been acquired.
- it.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.INVERSE_DISPLAY.value)
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.INVERSE_DISPLAY.value)
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, rotatedBufferSize,
- R8G8B8A8_UNORM)
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed(1, 500 /* ms */), 0)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!,
+ rotatedBufferSize, R8G8B8A8_UNORM)
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(1, 1000 /* ms */))
// Change buffer size and set scaling mode to freeze
- it.mSurfaceProxy.ANativeWindowSetBuffersGeometry(it.surface!!, Point(0, 0),
+ activity.mSurfaceProxy.ANativeWindowSetBuffersGeometry(activity.surface!!, Point(0, 0),
R8G8B8A8_UNORM)
// first dequeued buffer does not have the new size so it should be rejected.
- it.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.ROT_90.value)
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
- it.mSurfaceProxy.ANativeWindowSetBuffersTransform(0)
- it.mSurfaceProxy.SurfaceQueueBuffer(1)
- assertEquals(it.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersTransform(Transform.ROT_90.value)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ activity.mSurfaceProxy.ANativeWindowSetBuffersTransform(0)
+ activity.mSurfaceProxy.SurfaceQueueBuffer(1)
+ assertEquals(activity.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */), 0)
}
// verify buffer size is reset to default buffer size
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt b/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt
index ed79054..5f398f3 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/MainActivity.kt
@@ -40,12 +40,12 @@
private var mSurfaceHolder: SurfaceHolder? = null
private val mDrawLock = ReentrantLock()
var mSurfaceView: SurfaceView? = null
+ private var mCountDownLatch: CountDownLatch? = null
val surface: Surface? get() = mSurfaceHolder?.surface
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- addSurfaceView(Point(500, 200))
window.decorView.apply {
systemUiVisibility =
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN
@@ -60,13 +60,23 @@
val layout = findViewById<FrameLayout>(android.R.id.content)
val surfaceReadyLatch = CountDownLatch(1)
mSurfaceView = createSurfaceView(applicationContext, size, surfaceReadyLatch)
- layout.addView(mSurfaceView!!,
+ layout!!.addView(mSurfaceView!!,
FrameLayout.LayoutParams(size.x, size.y, Gravity.TOP or Gravity.LEFT)
.also { it.setMargins(100, 100, 0, 0) })
return surfaceReadyLatch
}
+ fun resizeSurfaceView(size: Point): CountDownLatch {
+ mCountDownLatch = CountDownLatch(1)
+ mSurfaceView!!.layoutParams.also {
+ it.width = size.x
+ it.height = size.y
+ }
+ mSurfaceView!!.requestLayout()
+ return mCountDownLatch!!
+ }
+
fun enableSeamlessRotation() {
val p: WindowManager.LayoutParams = window.attributes
p.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
@@ -88,7 +98,6 @@
): SurfaceView {
val surfaceView = SurfaceView(context)
surfaceView.setWillNotDraw(false)
- surfaceView.holder.setFixedSize(size.x, size.y)
surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
mDrawLock.withLock {
@@ -104,6 +113,7 @@
width: Int,
height: Int
) {
+ mCountDownLatch?.countDown()
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
index ae662506..ee41d79 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SharedBufferModeTests.kt
@@ -30,12 +30,12 @@
@Test
fun testCanPresentBuffers() {
val numFrames = 15L
- val trace = withTrace {
- assertEquals(0, it.mSurfaceProxy.NativeWindowSetSharedBufferMode(true))
+ val trace = withTrace { activity ->
+ assertEquals(0, activity.mSurfaceProxy.NativeWindowSetSharedBufferMode(true))
for (i in 1..numFrames) {
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
- assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(i, 5000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
+ assertEquals(0, activity.mSurfaceProxy.waitUntilBufferDisplayed(i, 5000 /* ms */))
}
}
@@ -47,13 +47,14 @@
@Test
fun testFastQueueBuffers() {
val numFrames = 15L
- val trace = withTrace {
- assertEquals(0, it.mSurfaceProxy.NativeWindowSetSharedBufferMode(true))
+ val trace = withTrace { activity ->
+ assertEquals(0, activity.mSurfaceProxy.NativeWindowSetSharedBufferMode(true))
for (i in 1..numFrames) {
- assertEquals(0, it.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
- it.mSurfaceProxy.SurfaceQueueBuffer(0)
+ assertEquals(0, activity.mSurfaceProxy.SurfaceDequeueBuffer(0, 1 /* ms */))
+ activity.mSurfaceProxy.SurfaceQueueBuffer(0)
}
- assertEquals(0, it.mSurfaceProxy.waitUntilBufferDisplayed(numFrames, 5000 /* ms */))
+ assertEquals(0, activity.mSurfaceProxy.waitUntilBufferDisplayed(numFrames,
+ 5000 /* ms */))
}
assertThat(trace).hasFrameSequence("SurfaceView", numFrames..numFrames)
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
index 273833b..8ea23de 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
@@ -60,6 +60,13 @@
}
}
+ fun withTrace(predicate: () -> Unit): LayersTrace {
+ return withSFTracing(TRACE_FLAGS,
+ outputDir = instrumentation.targetContext.dataDir.toPath()) {
+ predicate()
+ }
+ }
+
fun runOnUiThread(predicate: (it: MainActivity) -> Unit) {
scenarioRule.getScenario().onActivity {
predicate(it)
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
index bb985d7..53269ef 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
@@ -164,7 +164,7 @@
intent.putExtra(EXTRA_KEY_TIMEOUT, true);
mUsageStatsManager.registerAppUsageObserver(1, packages,
60, TimeUnit.SECONDS, PendingIntent.getActivity(UsageStatsActivity.this,
- 1, intent, 0));
+ 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED));
}
}
});
@@ -198,7 +198,7 @@
intent.putExtra(EXTRA_KEY_TIMEOUT, true);
mUsageStatsManager.registerAppUsageLimitObserver(1, packages,
Duration.ofSeconds(60), Duration.ofSeconds(0),
- PendingIntent.getActivity(UsageStatsActivity.this, 1, intent, 0));
+ PendingIntent.getActivity(UsageStatsActivity.this, 1, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED));
}
}
});
diff --git a/tests/UsbHostExternalManagmentTest/AoapTestDevice/src/com/android/hardware/usb/aoapdevicetest/UsbAoapDeviceTestActivity.java b/tests/UsbHostExternalManagmentTest/AoapTestDevice/src/com/android/hardware/usb/aoapdevicetest/UsbAoapDeviceTestActivity.java
index aa4f8ca..ef179e2 100644
--- a/tests/UsbHostExternalManagmentTest/AoapTestDevice/src/com/android/hardware/usb/aoapdevicetest/UsbAoapDeviceTestActivity.java
+++ b/tests/UsbHostExternalManagmentTest/AoapTestDevice/src/com/android/hardware/usb/aoapdevicetest/UsbAoapDeviceTestActivity.java
@@ -99,7 +99,7 @@
Intent intent = new Intent(ACTION_USB_ACCESSORY_PERMISSION);
intent.setPackage(getPackageName());
PendingIntent pendingIntent = PendingIntent.getBroadcast(
- this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+ this, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
mUsbManager.requestPermission(accessory, pendingIntent);
return;
}
diff --git a/tests/net/common/java/android/net/CaptivePortalDataTest.kt b/tests/net/common/java/android/net/CaptivePortalDataTest.kt
index 8710d23..2cb16d3372 100644
--- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt
+++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt
@@ -18,12 +18,15 @@
import android.os.Build
import androidx.test.filters.SmallTest
+import com.android.modules.utils.build.SdkLevel
import com.android.testutils.assertParcelSane
import com.android.testutils.assertParcelingIsLossless
+import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
@@ -33,6 +36,9 @@
@RunWith(DevSdkIgnoreRunner::class)
@IgnoreUpTo(Build.VERSION_CODES.Q)
class CaptivePortalDataTest {
+ @Rule @JvmField
+ val ignoreRule = DevSdkIgnoreRule()
+
private val data = CaptivePortalData.Builder()
.setRefreshTime(123L)
.setUserPortalUrl(Uri.parse("https://portal.example.com/test"))
@@ -41,7 +47,11 @@
.setBytesRemaining(456L)
.setExpiryTime(789L)
.setCaptive(true)
- .setVenueFriendlyName("venue friendly name")
+ .apply {
+ if (SdkLevel.isAtLeastS()) {
+ setVenueFriendlyName("venue friendly name")
+ }
+ }
.build()
private fun makeBuilder() = CaptivePortalData.Builder(data)
@@ -67,8 +77,11 @@
assertNotEqualsAfterChange { it.setBytesRemaining(789L) }
assertNotEqualsAfterChange { it.setExpiryTime(12L) }
assertNotEqualsAfterChange { it.setCaptive(false) }
- assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") }
- assertNotEqualsAfterChange { it.setVenueFriendlyName(null) }
+
+ if (SdkLevel.isAtLeastS()) {
+ assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") }
+ assertNotEqualsAfterChange { it.setVenueFriendlyName(null) }
+ }
}
@Test
@@ -111,7 +124,7 @@
assertFalse(makeBuilder().setCaptive(false).build().isCaptive)
}
- @Test
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
fun testVenueFriendlyName() {
assertEquals("venue friendly name", data.venueFriendlyName)
}
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 8e18751..16c4865 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -46,8 +46,6 @@
import com.android.server.LocalServices
import com.android.server.NetworkAgentWrapper
import com.android.server.TestNetIdManager
-import com.android.server.connectivity.DefaultNetworkMetrics
-import com.android.server.connectivity.IpConnectivityMetrics
import com.android.server.connectivity.MockableSystemProperties
import com.android.server.connectivity.ProxyTracker
import com.android.server.net.NetworkPolicyManagerInternal
@@ -92,10 +90,6 @@
private lateinit var netd: INetd
@Mock
private lateinit var dnsResolver: IDnsResolver
- @Mock
- private lateinit var metricsLogger: IpConnectivityMetrics.Logger
- @Mock
- private lateinit var defaultMetrics: DefaultNetworkMetrics
@Spy
private var context = TestableContext(realContext)
@@ -149,7 +143,6 @@
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- doReturn(defaultMetrics).`when`(metricsLogger).defaultNetworkMetrics()
doNothing().`when`(context).sendStickyBroadcastAsUser(any(), any(), any())
networkStackClient = TestNetworkStackClient(realContext)
@@ -173,7 +166,6 @@
private fun makeDependencies(): ConnectivityService.Dependencies {
val deps = spy(ConnectivityService.Dependencies())
doReturn(networkStackClient).`when`(deps).networkStack
- doReturn(metricsLogger).`when`(deps).metricsLogger
doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any())
doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties
doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager()
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index d74a621..f2dd27e 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -16,6 +16,7 @@
package android.net;
+import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
@@ -31,16 +32,21 @@
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkRequest.Type.REQUEST;
+import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -49,9 +55,7 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.pm.ApplicationInfo;
-import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
-import android.net.NetworkCapabilities;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
@@ -213,9 +217,8 @@
ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
// register callback
- when(mService.requestNetwork(
- any(), captor.capture(), anyInt(), any(), anyInt(), any(), nullable(String.class)))
- .thenReturn(request);
+ when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
+ any(), nullable(String.class))).thenReturn(request);
manager.requestNetwork(request, callback, handler);
// callback triggers
@@ -242,9 +245,8 @@
ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
// register callback
- when(mService.requestNetwork(
- any(), captor.capture(), anyInt(), any(), anyInt(), any(), nullable(String.class)))
- .thenReturn(req1);
+ when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
+ any(), nullable(String.class))).thenReturn(req1);
manager.requestNetwork(req1, callback, handler);
// callback triggers
@@ -261,9 +263,8 @@
verify(callback, timeout(100).times(0)).onLosing(any(), anyInt());
// callback can be registered again
- when(mService.requestNetwork(
- any(), captor.capture(), anyInt(), any(), anyInt(), any(), nullable(String.class)))
- .thenReturn(req2);
+ when(mService.requestNetwork(any(), anyInt(), captor.capture(), anyInt(), any(), anyInt(),
+ any(), nullable(String.class))).thenReturn(req2);
manager.requestNetwork(req2, callback, handler);
// callback triggers
@@ -286,7 +287,7 @@
info.targetSdkVersion = VERSION_CODES.N_MR1 + 1;
when(mCtx.getApplicationInfo()).thenReturn(info);
- when(mService.requestNetwork(any(), any(), anyInt(), any(), anyInt(), any(),
+ when(mService.requestNetwork(any(), anyInt(), any(), anyInt(), any(), anyInt(), any(),
nullable(String.class))).thenReturn(request);
Handler handler = new Handler(Looper.getMainLooper());
@@ -340,6 +341,35 @@
}
}
+ @Test
+ public void testRequestType() throws Exception {
+ final String testPkgName = "MyPackage";
+ final ConnectivityManager manager = new ConnectivityManager(mCtx, mService);
+ when(mCtx.getOpPackageName()).thenReturn(testPkgName);
+ final NetworkRequest request = makeRequest(1);
+ final NetworkCallback callback = new ConnectivityManager.NetworkCallback();
+
+ manager.requestNetwork(request, callback);
+ verify(mService).requestNetwork(eq(request.networkCapabilities),
+ eq(REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE),
+ eq(testPkgName), eq(null));
+ reset(mService);
+
+ // Verify that register network callback does not calls requestNetwork at all.
+ manager.registerNetworkCallback(request, callback);
+ verify(mService, never()).requestNetwork(any(), anyInt(), any(), anyInt(), any(),
+ anyInt(), any(), any());
+ verify(mService).listenForNetwork(eq(request.networkCapabilities), any(), any(),
+ eq(testPkgName));
+ reset(mService);
+
+ manager.registerDefaultNetworkCallback(callback);
+ verify(mService).requestNetwork(eq(null),
+ eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE),
+ eq(testPkgName), eq(null));
+ reset(mService);
+ }
+
static Message makeMessage(NetworkRequest req, int messageType) {
Bundle bundle = new Bundle();
bundle.putParcelable(NetworkRequest.class.getSimpleName(), req);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 12e4ad2..ad8979c 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -243,8 +243,6 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
import com.android.server.connectivity.ConnectivityConstants;
-import com.android.server.connectivity.DefaultNetworkMetrics;
-import com.android.server.connectivity.IpConnectivityMetrics;
import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.NetworkAgentInfo;
@@ -290,13 +288,16 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -364,8 +365,6 @@
private HandlerThread mAlarmManagerThread;
private TestNetIdManager mNetIdManager;
- @Mock IpConnectivityMetrics.Logger mMetricsService;
- @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
@Mock DeviceIdleInternal mDeviceIdleInternal;
@Mock INetworkManagementService mNetworkManagementService;
@Mock INetworkStatsService mStatsService;
@@ -411,9 +410,6 @@
private class MockContext extends BroadcastInterceptingContext {
private final MockContentResolver mContentResolver;
- // Contains all registered receivers since this object was created. Useful to clear
- // them when needed, as BroadcastInterceptingContext does not provide this facility.
- private final List<BroadcastReceiver> mRegisteredReceivers = new ArrayList<>();
@Spy private Resources mResources;
private final LinkedBlockingQueue<Intent> mStartedActivities = new LinkedBlockingQueue<>();
@@ -550,19 +546,6 @@
public void setPermission(String permission, Integer granted) {
mMockedPermissions.put(permission, granted);
}
-
- @Override
- public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
- mRegisteredReceivers.add(receiver);
- return super.registerReceiver(receiver, filter);
- }
-
- public void clearRegisteredReceivers() {
- // super.unregisterReceiver is a no-op for receivers that are not registered (because
- // they haven't been registered or because they have already been unregistered).
- // For the same reason, don't bother clearing mRegisteredReceivers.
- for (final BroadcastReceiver rcv : mRegisteredReceivers) unregisterReceiver(rcv);
- }
}
private void waitForIdle() {
@@ -591,10 +574,10 @@
}
// Bring up a network that we can use to send messages to ConnectivityService.
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
Network n = mWiFiNetworkAgent.getNetwork();
assertNotNull(n);
@@ -611,10 +594,10 @@
@Ignore
public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
// Bring up a network that we can use to send messages to ConnectivityService.
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
Network n = mWiFiNetworkAgent.getNetwork();
assertNotNull(n);
@@ -1300,7 +1283,6 @@
mContext = InstrumentationRegistry.getContext();
MockitoAnnotations.initMocks(this);
- when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
when(mUserManager.getAliveUsers()).thenReturn(
Arrays.asList(new UserInfo[] {
@@ -1375,7 +1357,6 @@
doReturn(mNetworkStack).when(deps).getNetworkStack();
doReturn(mSystemProperties).when(deps).getSystemProperties();
doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
- doReturn(mMetricsService).when(deps).getMetricsLogger();
doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
doAnswer(inv -> {
@@ -1514,29 +1495,79 @@
}
/**
- * Return a ConditionVariable that opens when {@code count} numbers of CONNECTIVITY_ACTION
- * broadcasts are received.
+ * Class to simplify expecting broadcasts using BroadcastInterceptingContext.
+ * Ensures that the receiver is unregistered after the expected broadcast is received. This
+ * cannot be done in the BroadcastReceiver itself because BroadcastInterceptingContext runs
+ * the receivers' receive method while iterating over the list of receivers, and unregistering
+ * the receiver during iteration throws ConcurrentModificationException.
*/
- private ConditionVariable registerConnectivityBroadcast(final int count) {
+ private class ExpectedBroadcast extends CompletableFuture<Intent> {
+ private final BroadcastReceiver mReceiver;
+
+ ExpectedBroadcast(BroadcastReceiver receiver) {
+ mReceiver = receiver;
+ }
+
+ public Intent expectBroadcast(int timeoutMs) throws Exception {
+ try {
+ return get(timeoutMs, TimeUnit.MILLISECONDS);
+ } catch (TimeoutException e) {
+ fail("Expected broadcast not received after " + timeoutMs + " ms");
+ return null;
+ } finally {
+ mServiceContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ public Intent expectBroadcast() throws Exception {
+ return expectBroadcast(TIMEOUT_MS);
+ }
+
+ public void expectNoBroadcast(int timeoutMs) throws Exception {
+ waitForIdle();
+ try {
+ final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
+ fail("Unexpected broadcast: " + intent.getAction());
+ } catch (TimeoutException expected) {
+ } finally {
+ mServiceContext.unregisterReceiver(mReceiver);
+ }
+ }
+ }
+
+ /** Expects that {@code count} CONNECTIVITY_ACTION broadcasts are received. */
+ private ExpectedBroadcast registerConnectivityBroadcast(final int count) {
return registerConnectivityBroadcastThat(count, intent -> true);
}
- private ConditionVariable registerConnectivityBroadcastThat(final int count,
+ private ExpectedBroadcast registerConnectivityBroadcastThat(final int count,
@NonNull final Predicate<Intent> filter) {
- final ConditionVariable cv = new ConditionVariable();
final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION);
+ // AtomicReference allows receiver to access expected even though it is constructed later.
+ final AtomicReference<ExpectedBroadcast> expectedRef = new AtomicReference<>();
final BroadcastReceiver receiver = new BroadcastReceiver() {
- private int remaining = count;
- public void onReceive(Context context, Intent intent) {
- if (!filter.test(intent)) return;
- if (--remaining == 0) {
- cv.open();
- mServiceContext.unregisterReceiver(this);
- }
- }
- };
+ private int mRemaining = count;
+ public void onReceive(Context context, Intent intent) {
+ final int type = intent.getIntExtra(EXTRA_NETWORK_TYPE, -1);
+ final NetworkInfo ni = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
+ Log.d(TAG, "Received CONNECTIVITY_ACTION type=" + type + " ni=" + ni);
+ if (!filter.test(intent)) return;
+ if (--mRemaining == 0) {
+ expectedRef.get().complete(intent);
+ }
+ }
+ };
+ final ExpectedBroadcast expected = new ExpectedBroadcast(receiver);
+ expectedRef.set(expected);
mServiceContext.registerReceiver(receiver, intentFilter);
- return cv;
+ return expected;
+ }
+
+ private ExpectedBroadcast expectConnectivityAction(int type, NetworkInfo.DetailedState state) {
+ return registerConnectivityBroadcastThat(1, intent ->
+ type == intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) && state.equals(
+ ((NetworkInfo) intent.getParcelableExtra(EXTRA_NETWORK_INFO))
+ .getDetailedState()));
}
@Test
@@ -1560,10 +1591,9 @@
// Connect the cell agent and wait for the connected broadcast.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_SUPL);
- final ConditionVariable cv1 = registerConnectivityBroadcastThat(1,
- intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
mCellNetworkAgent.connect(true);
- waitFor(cv1);
+ b.expectBroadcast();
// Build legacy request for SUPL.
final NetworkCapabilities legacyCaps = new NetworkCapabilities();
@@ -1573,27 +1603,17 @@
ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST);
// File request, withdraw it and make sure no broadcast is sent
- final ConditionVariable cv2 = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
final TestNetworkCallback callback = new TestNetworkCallback();
mCm.requestNetwork(legacyRequest, callback);
callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent);
mCm.unregisterNetworkCallback(callback);
- assertFalse(cv2.block(800)); // 800ms long enough to at least flake if this is sent
- // As the broadcast did not fire, the receiver was not unregistered. Do this now.
- mServiceContext.clearRegisteredReceivers();
+ b.expectNoBroadcast(800); // 800ms long enough to at least flake if this is sent
- // Disconnect the network and expect mobile disconnected broadcast. Use a small hack to
- // check that has been sent.
- final AtomicBoolean vanillaAction = new AtomicBoolean(false);
- final ConditionVariable cv3 = registerConnectivityBroadcastThat(1, intent -> {
- if (intent.getAction().equals(CONNECTIVITY_ACTION)) {
- vanillaAction.set(true);
- }
- return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected();
- });
+ // Disconnect the network and expect mobile disconnected broadcast.
+ b = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
mCellNetworkAgent.disconnect();
- waitFor(cv3);
- assertTrue(vanillaAction.get());
+ b.expectBroadcast();
}
@Test
@@ -1604,9 +1624,9 @@
assertNull(mCm.getActiveNetworkInfo());
assertNull(mCm.getActiveNetwork());
// Test bringing up validated cellular.
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
assertLength(2, mCm.getAllNetworks());
assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
@@ -1614,9 +1634,9 @@
assertTrue(mCm.getAllNetworks()[0].equals(mWiFiNetworkAgent.getNetwork()) ||
mCm.getAllNetworks()[1].equals(mWiFiNetworkAgent.getNetwork()));
// Test bringing up validated WiFi.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
assertLength(2, mCm.getAllNetworks());
assertTrue(mCm.getAllNetworks()[0].equals(mCm.getActiveNetwork()) ||
@@ -1631,9 +1651,9 @@
assertLength(1, mCm.getAllNetworks());
assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
// Test WiFi disconnect.
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyNoNetwork();
}
@@ -1641,9 +1661,9 @@
public void testValidatedCellularOutscoresUnvalidatedWiFi() throws Exception {
// Test bringing up unvalidated WiFi
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up unvalidated cellular
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
@@ -1656,19 +1676,19 @@
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test cellular disconnect.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi disconnect.
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyNoNetwork();
}
@@ -1676,25 +1696,25 @@
public void testUnvalidatedWifiOutscoresUnvalidatedCellular() throws Exception {
// Test bringing up unvalidated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mCellNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi disconnect.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test cellular disconnect.
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mCellNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyNoNetwork();
}
@@ -1702,24 +1722,24 @@
public void testUnlingeringDoesNotValidate() throws Exception {
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
// Test bringing up validated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
// Test cellular disconnect.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Unlingering a network should not cause it to be marked as validated.
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
@@ -1730,25 +1750,25 @@
public void testCellularOutscoresWeakWifi() throws Exception {
// Test bringing up validated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test WiFi getting really weak.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.adjustScore(-11);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test WiFi restoring signal strength.
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.adjustScore(11);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
}
@@ -1766,9 +1786,9 @@
mCellNetworkAgent.expectDisconnected();
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- final ConditionVariable cv = registerConnectivityBroadcast(1);
+ final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up unvalidated cellular.
// Expect it to be torn down because it could never be the highest scoring network
@@ -1785,33 +1805,33 @@
public void testCellularFallback() throws Exception {
// Test bringing up validated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Reevaluate WiFi (it'll instantly fail DNS).
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
assertTrue(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mWiFiNetworkAgent.getNetwork());
// Should quickly fall back to Cellular.
- waitFor(cv);
+ b.expectBroadcast();
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Reevaluate cellular (it'll instantly fail DNS).
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
// Should quickly fall back to WiFi.
- waitFor(cv);
+ b.expectBroadcast();
assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
assertFalse(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).hasCapability(
@@ -1823,23 +1843,23 @@
public void testWiFiFallback() throws Exception {
// Test bringing up unvalidated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mWiFiNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Test bringing up validated cellular.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Reevaluate cellular (it'll instantly fail DNS).
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
assertTrue(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
mCm.reportBadNetwork(mCellNetworkAgent.getNetwork());
// Should quickly fall back to WiFi.
- waitFor(cv);
+ b.expectBroadcast();
assertFalse(mCm.getNetworkCapabilities(mCellNetworkAgent.getNetwork()).hasCapability(
NET_CAPABILITY_VALIDATED));
verifyActiveNetwork(TRANSPORT_WIFI);
@@ -1909,13 +1929,13 @@
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
// Test unvalidated networks
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
cellNetworkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- waitFor(cv);
+ b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
// This should not trigger spurious onAvailable() callbacks, b/21762680.
@@ -1924,28 +1944,28 @@
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(false);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
- waitFor(cv);
+ b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
- cv = registerConnectivityBroadcast(2);
+ b = registerConnectivityBroadcast(2);
mWiFiNetworkAgent.disconnect();
genericNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
wifiNetworkCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
cellNetworkCallback.assertNoCallback();
- waitFor(cv);
+ b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mCellNetworkAgent.disconnect();
genericNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
- waitFor(cv);
+ b.expectBroadcast();
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
// Test validated networks
@@ -2048,10 +2068,6 @@
@Test
public void testOwnerUidCannotChange() throws Exception {
- // Owner UIDs are not visible without location permission.
- setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION);
-
final NetworkCapabilities ncTemplate = new NetworkCapabilities();
final int originalOwnerUid = Process.myUid();
ncTemplate.setOwnerUid(originalOwnerUid);
@@ -2071,6 +2087,10 @@
mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
waitForIdle();
+ // Owner UIDs are not visible without location permission.
+ setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION);
+
// Check that the capability change has been applied but the owner UID is not modified.
NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
assertEquals(originalOwnerUid, nc.getOwnerUid());
@@ -2666,9 +2686,9 @@
// Test bringing up validated WiFi.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- final ConditionVariable cv = registerConnectivityBroadcast(1);
+ final ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
// Register MMS NetworkRequest
@@ -2694,9 +2714,9 @@
public void testMMSonCell() throws Exception {
// Test bringing up cellular without MMS
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
mCellNetworkAgent.connect(false);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_CELLULAR);
// Register MMS NetworkRequest
@@ -3361,8 +3381,8 @@
NetworkCapabilities networkCapabilities = new NetworkCapabilities();
networkCapabilities.addTransportType(TRANSPORT_WIFI)
.setNetworkSpecifier(new MatchAllNetworkSpecifier());
- mService.requestNetwork(networkCapabilities, null, 0, null,
- ConnectivityManager.TYPE_WIFI, mContext.getPackageName(),
+ mService.requestNetwork(networkCapabilities, NetworkRequest.Type.REQUEST.ordinal(),
+ null, 0, null, ConnectivityManager.TYPE_WIFI, mContext.getPackageName(),
getAttributionTag());
});
@@ -4304,9 +4324,9 @@
}
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
mWiFiNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
verifyActiveNetwork(TRANSPORT_WIFI);
mWiFiNetworkAgent.sendLinkProperties(lp);
waitForIdle();
@@ -4862,10 +4882,10 @@
assertNotPinnedToWifi();
// Disconnect cell and wifi.
- ConditionVariable cv = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
+ ExpectedBroadcast b = registerConnectivityBroadcast(3); // cell down, wifi up, wifi down.
mCellNetworkAgent.disconnect();
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
// Pinning takes effect even if the pinned network is the default when the pin is set...
TestNetworkPinner.pin(mServiceContext, wifiRequest);
@@ -4875,10 +4895,10 @@
assertPinnedToWifiWithWifiDefault();
// ... and is maintained even when that network is no longer the default.
- cv = registerConnectivityBroadcast(1);
+ b = registerConnectivityBroadcast(1);
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mCellNetworkAgent.connect(true);
- waitFor(cv);
+ b.expectBroadcast();
assertPinnedToWifiWithCellDefault();
}
@@ -4978,7 +4998,7 @@
@Test
public void testNetworkInfoOfTypeNone() throws Exception {
- ConditionVariable broadcastCV = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = registerConnectivityBroadcast(1);
verifyNoNetwork();
TestNetworkAgentWrapper wifiAware = new TestNetworkAgentWrapper(TRANSPORT_WIFI_AWARE);
@@ -5011,9 +5031,7 @@
mCm.unregisterNetworkCallback(callback);
verifyNoNetwork();
- if (broadcastCV.block(10)) {
- fail("expected no broadcast, but got CONNECTIVITY_ACTION broadcast");
- }
+ b.expectNoBroadcast(10);
}
@Test
@@ -6325,7 +6343,7 @@
// Create a fake restricted profile whose parent is our user ID.
final int userId = UserHandle.getUserId(uid);
- when(mUserManager.canHaveRestrictedProfile(userId)).thenReturn(true);
+ when(mUserManager.canHaveRestrictedProfile()).thenReturn(true);
final int restrictedUserId = userId + 1;
final UserInfo info = new UserInfo(restrictedUserId, "user", UserInfo.FLAG_RESTRICTED);
info.restrictedProfileParentId = userId;
@@ -7250,11 +7268,11 @@
// prefix discovery is never started.
LinkProperties lp = new LinkProperties(baseLp);
lp.setNat64Prefix(pref64FromRa);
- mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
- mCellNetworkAgent.connect(false);
- final Network network = mCellNetworkAgent.getNetwork();
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
+ mWiFiNetworkAgent.connect(false);
+ final Network network = mWiFiNetworkAgent.getNetwork();
int netId = network.getNetId();
- callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
@@ -7263,8 +7281,8 @@
// If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started.
lp.setNat64Prefix(null);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, null);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
@@ -7272,8 +7290,8 @@
// If the RA prefix appears while DNS discovery is in progress, discovery is stopped and
// clatd is started with the prefix from the RA.
lp.setNat64Prefix(pref64FromRa);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString());
@@ -7281,21 +7299,21 @@
// Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS
// discovery has succeeded.
lp.setNat64Prefix(null);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, null);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
pref64FromDnsStr, 96);
- expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
// If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
// discovery is not stopped, and there are no callbacks.
lp.setNat64Prefix(pref64FromDns);
- mCellNetworkAgent.sendLinkProperties(lp);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
inOrder.verify(mMockNetd, never()).clatdStop(iface);
inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
@@ -7305,7 +7323,7 @@
// If the RA is later withdrawn, nothing happens again.
lp.setNat64Prefix(null);
- mCellNetworkAgent.sendLinkProperties(lp);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
inOrder.verify(mMockNetd, never()).clatdStop(iface);
inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
@@ -7315,8 +7333,8 @@
// If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
lp.setNat64Prefix(pref64FromRa);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromRa);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
@@ -7330,8 +7348,8 @@
// If the RA prefix changes, clatd is restarted and prefix discovery is not started.
lp.setNat64Prefix(newPref64FromRa);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, newPref64FromRa);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, newPref64FromRa);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString());
@@ -7341,7 +7359,7 @@
// If the RA prefix changes to the same value, nothing happens.
lp.setNat64Prefix(newPref64FromRa);
- mCellNetworkAgent.sendLinkProperties(lp);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix());
inOrder.verify(mMockNetd, never()).clatdStop(iface);
@@ -7355,19 +7373,19 @@
// If the same prefix is learned first by DNS and then by RA, and clat is later stopped,
// (e.g., because the network disconnects) setPrefix64(netid, "") is never called.
lp.setNat64Prefix(null);
- mCellNetworkAgent.sendLinkProperties(lp);
- expectNat64PrefixChange(callback, mCellNetworkAgent, null);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, null);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).setPrefix64(netId, "");
inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId);
mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */,
pref64FromDnsStr, 96);
- expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns);
+ expectNat64PrefixChange(callback, mWiFiNetworkAgent, pref64FromDns);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any());
lp.setNat64Prefix(pref64FromDns);
- mCellNetworkAgent.sendLinkProperties(lp);
+ mWiFiNetworkAgent.sendLinkProperties(lp);
callback.assertNoCallback();
inOrder.verify(mMockNetd, never()).clatdStop(iface);
inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
@@ -7378,10 +7396,10 @@
// When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but
// before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that
// clat has been stopped, or the test will be flaky.
- ConditionVariable cv = registerConnectivityBroadcast(1);
- mCellNetworkAgent.disconnect();
- callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
- waitFor(cv);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
+ mWiFiNetworkAgent.disconnect();
+ callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+ b.expectBroadcast();
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
@@ -7406,7 +7424,7 @@
mCellNetworkAgent.connect(true);
networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
- eq(ConnectivityManager.TYPE_MOBILE));
+ eq(NetworkCapabilities.TRANSPORT_CELLULAR));
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
final LinkProperties wifiLp = new LinkProperties();
@@ -7420,7 +7438,7 @@
networkCallback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
- eq(ConnectivityManager.TYPE_WIFI));
+ eq(NetworkCapabilities.TRANSPORT_WIFI));
verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(MOBILE_IFNAME));
// Disconnect wifi and switch back to cell
@@ -7430,7 +7448,7 @@
assertNoCallbacks(networkCallback);
verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
- eq(ConnectivityManager.TYPE_MOBILE));
+ eq(NetworkCapabilities.TRANSPORT_CELLULAR));
// reconnect wifi
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
@@ -7456,10 +7474,10 @@
.destroyNetworkCache(eq(mCellNetworkAgent.getNetwork().netId));
// Disconnect wifi
- ConditionVariable cv = registerConnectivityBroadcast(1);
+ ExpectedBroadcast b = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
reset(mNetworkManagementService);
mWiFiNetworkAgent.disconnect();
- waitFor(cv);
+ b.expectBroadcast();
verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
// Clean up
@@ -7757,8 +7775,22 @@
naExtraInfo.unregister();
}
+ // To avoid granting location permission bypass.
+ private void denyAllLocationPrivilegedPermissions() {
+ mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ PERMISSION_DENIED);
+ mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
+ PERMISSION_DENIED);
+ mServiceContext.setPermission(Manifest.permission.NETWORK_STACK,
+ PERMISSION_DENIED);
+ mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
+ PERMISSION_DENIED);
+ }
+
private void setupLocationPermissions(
int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
+ denyAllLocationPrivilegedPermissions();
+
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = targetSdk;
when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
@@ -8132,15 +8164,13 @@
new NetworkAgentInfo(null, network, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
- setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION);
-
mMockVpn.establishForMyUid();
assertUidRangesUpdatedForMyUid(true);
// Wait for networks to connect and broadcasts to be sent before removing permissions.
waitForIdle();
- mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+ setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION);
assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {network}));
waitForIdle();
@@ -8405,6 +8435,7 @@
mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
+ waitForIdle();
final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
@@ -8466,4 +8497,20 @@
assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
}
+
+ @Test
+ public void testInvalidRequestTypes() {
+ final int[] invalidReqTypeInts = new int[] {-1, NetworkRequest.Type.NONE.ordinal(),
+ NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length};
+ final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI);
+
+ for (int reqTypeInt : invalidReqTypeInts) {
+ assertThrows("Expect throws for invalid request type " + reqTypeInt,
+ IllegalArgumentException.class,
+ () -> mService.requestNetwork(nc, reqTypeInt, null, 0, null,
+ ConnectivityManager.TYPE_NONE, mContext.getPackageName(),
+ getAttributionTag())
+ );
+ }
+ }
}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 02a2aad..68aaaed 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -252,6 +252,7 @@
@Test
public void testRestrictedProfilesAreAddedToVpn() {
+ if (true) return; // TODO(b/175883995): Test disabled until updated for new UserManager API.
setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
final Vpn vpn = createVpn(primaryUser.id);
@@ -265,6 +266,7 @@
@Test
public void testManagedProfilesAreNotAddedToVpn() {
+ if (true) return; // TODO(b/175883995): Test disabled until updated for new UserManager API.
setMockedUsers(primaryUser, managedProfileA);
final Vpn vpn = createVpn(primaryUser.id);
@@ -287,6 +289,7 @@
@Test
public void testUidAllowAndDenylist() throws Exception {
+ if (true) return; // TODO(b/175883995): Test disabled until updated for new UserManager API.
final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = PRI_USER_RANGE;
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
@@ -312,6 +315,7 @@
@Test
public void testGetAlwaysAndOnGetLockDown() throws Exception {
+ if (true) return; // TODO(b/175883995): Test disabled until updated for new UserManager API.
final Vpn vpn = createVpn(primaryUser.id);
// Default state.
@@ -336,6 +340,7 @@
@Test
public void testLockdownChangingPackage() throws Exception {
+ if (true) return; // TODO(b/175883995): Test disabled until updated for new UserManager API.
final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = PRI_USER_RANGE;
@@ -363,6 +368,7 @@
@Test
public void testLockdownAllowlist() throws Exception {
+ if (true) return; // TODO(b/175883995): Test disabled until updated for new UserManager API.
final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = PRI_USER_RANGE;
@@ -437,6 +443,7 @@
@Test
public void testLockdownRuleRepeatability() throws Exception {
+ if (true) return; // TODO(b/175883995): Test disabled until updated for new UserManager API.
final Vpn vpn = createVpn(primaryUser.id);
final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] {
new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)};
@@ -469,6 +476,7 @@
@Test
public void testLockdownRuleReversibility() throws Exception {
+ if (true) return; // TODO(b/175883995): Test disabled until updated for new UserManager API.
final Vpn vpn = createVpn(primaryUser.id);
final UidRangeParcel[] entireUser = {
new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)
@@ -1174,7 +1182,7 @@
doAnswer(invocation -> {
final int id = (int) invocation.getArguments()[0];
return (userMap.get(id).flags & UserInfo.FLAG_ADMIN) != 0;
- }).when(mUserManager).canHaveRestrictedProfile(anyInt());
+ }).when(mUserManager).canHaveRestrictedProfile();
}
/**
diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp
index f967bf0..3c08d34 100644
--- a/tests/vcn/Android.bp
+++ b/tests/vcn/Android.bp
@@ -20,6 +20,7 @@
"services.core",
],
libs: [
+ "android.net.ipsec.ike.stubs.module_lib",
"android.test.runner",
"android.test.base",
"android.test.mock",
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index e98b6ef..dfd0c8a 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -33,12 +33,13 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnGatewayConnectionConfigTest {
- private static final int[] EXPOSED_CAPS =
+ // Public for use in VcnGatewayConnectionTest
+ public static final int[] EXPOSED_CAPS =
new int[] {
NetworkCapabilities.NET_CAPABILITY_INTERNET, NetworkCapabilities.NET_CAPABILITY_MMS
};
- private static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
- private static final long[] RETRY_INTERVALS_MS =
+ public static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
+ public static final long[] RETRY_INTERVALS_MS =
new long[] {
TimeUnit.SECONDS.toMillis(5),
TimeUnit.SECONDS.toMillis(30),
@@ -47,10 +48,10 @@
TimeUnit.MINUTES.toMillis(15),
TimeUnit.MINUTES.toMillis(30)
};
- private static final int MAX_MTU = 1360;
+ public static final int MAX_MTU = 1360;
- // Package protected for use in VcnConfigTest
- static VcnGatewayConnectionConfig buildTestConfig() {
+ // Public for use in VcnGatewayConnectionTest
+ public static VcnGatewayConnectionConfig buildTestConfig() {
final VcnGatewayConnectionConfig.Builder builder =
new VcnGatewayConnectionConfig.Builder()
.setRetryInterval(RETRY_INTERVALS_MS)
diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
new file mode 100644
index 0000000..3156190
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+
+import org.junit.Test;
+
+public class VcnTransportInfoTest {
+ private static final int SUB_ID = 1;
+ private static final int NETWORK_ID = 5;
+ private static final WifiInfo WIFI_INFO =
+ new WifiInfo.Builder().setNetworkId(NETWORK_ID).build();
+
+ private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID);
+ private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO);
+
+ @Test
+ public void testGetWifiInfo() {
+ assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo());
+
+ assertNull(CELL_UNDERLYING_INFO.getWifiInfo());
+ }
+
+ @Test
+ public void testGetSubId() {
+ assertEquals(SUB_ID, CELL_UNDERLYING_INFO.getSubId());
+
+ assertEquals(INVALID_SUBSCRIPTION_ID, WIFI_UNDERLYING_INFO.getSubId());
+ }
+
+ @Test
+ public void testEquals() {
+ assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO);
+ assertEquals(WIFI_UNDERLYING_INFO, WIFI_UNDERLYING_INFO);
+ assertNotEquals(CELL_UNDERLYING_INFO, WIFI_UNDERLYING_INFO);
+ }
+
+ @Test
+ public void testParcelUnparcel() {
+ verifyParcelingIsNull(CELL_UNDERLYING_INFO);
+ verifyParcelingIsNull(WIFI_UNDERLYING_INFO);
+ }
+
+ private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) {
+ Parcel parcel = Parcel.obtain();
+ vcnTransportInfo.writeToParcel(parcel, 0 /* flags */);
+ assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel));
+ }
+}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
new file mode 100644
index 0000000..d741e5c
--- /dev/null
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.NetworkCapabilities;
+import android.net.vcn.VcnGatewayConnectionConfigTest;
+import android.os.ParcelUuid;
+import android.os.test.TestLooper;
+import android.telephony.SubscriptionInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/** Tests for TelephonySubscriptionTracker */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VcnGatewayConnectionTest {
+ private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
+ private static final int TEST_SIM_SLOT_INDEX = 1;
+ private static final int TEST_SUBSCRIPTION_ID_1 = 2;
+ private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class);
+ private static final int TEST_SUBSCRIPTION_ID_2 = 3;
+ private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
+ private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;
+
+ static {
+ final Map<Integer, ParcelUuid> subIdToGroupMap = new HashMap<>();
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_PARCEL_UUID);
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_PARCEL_UUID);
+ TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap);
+ }
+
+ @NonNull private final Context mContext;
+ @NonNull private final TestLooper mTestLooper;
+ @NonNull private final VcnNetworkProvider mVcnNetworkProvider;
+ @NonNull private final VcnGatewayConnection.Dependencies mDeps;
+
+ public VcnGatewayConnectionTest() {
+ mContext = mock(Context.class);
+ mTestLooper = new TestLooper();
+ mVcnNetworkProvider = mock(VcnNetworkProvider.class);
+ mDeps = mock(VcnGatewayConnection.Dependencies.class);
+ }
+
+ @Test
+ public void testBuildNetworkCapabilities() throws Exception {
+ final NetworkCapabilities caps =
+ VcnGatewayConnection.buildNetworkCapabilities(
+ VcnGatewayConnectionConfigTest.buildTestConfig());
+
+ for (int exposedCapability : VcnGatewayConnectionConfigTest.EXPOSED_CAPS) {
+ assertTrue(caps.hasCapability(exposedCapability));
+ }
+ }
+}
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index ad716c7..daedc2a 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -227,8 +227,7 @@
apk_assets.push_back(apk_asset.get());
}
- asset_manager_.SetApkAssets(apk_assets, true /* invalidate_caches */,
- false /* filter_incompatible_configs */);
+ asset_manager_.SetApkAssets(apk_assets);
return true;
}
return false;
@@ -351,9 +350,9 @@
return true;
}
- auto value = asset_manager_.GetResource(res_id.id, true /* may_be_bag */);
- if (value.has_value()) {
- type_spec_flags = value->flags;
+ auto flags = asset_manager_.GetResourceTypeSpecFlags(res_id.id);
+ if (flags.has_value()) {
+ type_spec_flags = *flags;
found = true;
return false;
}
@@ -406,8 +405,8 @@
return {};
}
- auto value = asset_manager_.GetResource(id.id, true /* may_be_bag */);
- if (!value.has_value()) {
+ auto flags = asset_manager_.GetResourceTypeSpecFlags(id.id);
+ if (!flags.has_value()) {
return {};
}
@@ -422,7 +421,7 @@
}
if (s) {
- s->is_public = (value->flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
+ s->is_public = (*flags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0;
return s;
}
return {};