Merge "PowerStats: adjust time since boot to epoch before writing to disk" into sc-dev
diff --git a/apct-tests/perftests/contentcapture/Android.bp b/apct-tests/perftests/contentcapture/Android.bp
index 19a66ad..638403d 100644
--- a/apct-tests/perftests/contentcapture/Android.bp
+++ b/apct-tests/perftests/contentcapture/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "ContentCapturePerfTests",
srcs: ["src/**/*.java"],
diff --git a/apct-tests/perftests/inputmethod/Android.bp b/apct-tests/perftests/inputmethod/Android.bp
index 463ac9b..f2f1f75 100644
--- a/apct-tests/perftests/inputmethod/Android.bp
+++ b/apct-tests/perftests/inputmethod/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "ImePerfTests",
srcs: ["src/**/*.java"],
diff --git a/apex/appsearch/Android.bp b/apex/appsearch/Android.bp
index ab44dd9..87f65a9 100644
--- a/apex/appsearch/Android.bp
+++ b/apex/appsearch/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
apex {
name: "com.android.appsearch",
manifest: "apex_manifest.json",
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index 8ba7954..5def55f 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "framework-appsearch-sources",
srcs: [
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java
index 519c14f..31ab259 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java
@@ -28,11 +28,19 @@
import java.util.Map;
/**
- * Provides access to multiple {@link AppSearchResult}s from a batch operation accepting multiple
- * inputs.
+ * Provides results for AppSearch batch operations which encompass multiple documents.
*
- * @param <KeyType> The type of the keys for {@link #getSuccesses} and {@link #getFailures}.
- * @param <ValueType> The type of result objects associated with the keys.
+ * <p>Individual results of a batch operation are separated into two maps: one for successes and one
+ * for failures. For successes, {@link #getSuccesses()} will return a map of keys to instances of
+ * the value type. For failures, {@link #getFailures()} will return a map of keys to {@link
+ * AppSearchResult} objects.
+ *
+ * <p>Alternatively, {@link #getAll()} returns a map of keys to {@link AppSearchResult} objects for
+ * both successes and failures.
+ *
+ * @see AppSearchSession#put
+ * @see AppSearchSession#getByUri
+ * @see AppSearchSession#remove
*/
public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelable {
@NonNull private final Map<KeyType, ValueType> mSuccesses;
@@ -75,8 +83,11 @@
}
/**
- * Returns a {@link Map} of all successful keys mapped to the successful {@link
- * AppSearchResult}s they produced.
+ * Returns a {@link Map} of keys mapped to instances of the value type for all successful
+ * individual results.
+ *
+ * <p>Example: {@link AppSearchSession#getByUri} returns an {@link AppSearchBatchResult}. Each
+ * key (a URI of {@code String} type) will map to a {@link GenericDocument} object.
*
* <p>The values of the {@link Map} will not be {@code null}.
*/
@@ -86,8 +97,8 @@
}
/**
- * Returns a {@link Map} of all failed keys mapped to the failed {@link AppSearchResult}s they
- * produced.
+ * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all failed
+ * individual results.
*
* <p>The values of the {@link Map} will not be {@code null}.
*/
@@ -97,7 +108,8 @@
}
/**
- * Returns a {@link Map} of all keys mapped to the {@link AppSearchResult}s they produced.
+ * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all
+ * individual results.
*
* <p>The values of the {@link Map} will not be {@code null}.
*/
@@ -149,8 +161,8 @@
/**
* Builder for {@link AppSearchBatchResult} objects.
*
- * @param <KeyType> The type of keys.
- * @param <ValueType> The type of result objects associated with the keys.
+ * <p>Once {@link #build} is called, the instance can no longer be used.
+ *
* @hide
*/
public static final class Builder<KeyType, ValueType> {
@@ -160,9 +172,11 @@
private boolean mBuilt = false;
/**
- * Associates the {@code key} with the given successful return value.
+ * Associates the {@code key} with the provided successful return value.
*
* <p>Any previous mapping for a key, whether success or failure, is deleted.
+ *
+ * @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder<KeyType, ValueType> setSuccess(
@@ -173,9 +187,11 @@
}
/**
- * Associates the {@code key} with the given failure code and error message.
+ * Associates the {@code key} with the provided failure code and error message.
*
* <p>Any previous mapping for a key, whether success or failure, is deleted.
+ *
+ * @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder<KeyType, ValueType> setFailure(
@@ -188,9 +204,11 @@
}
/**
- * Associates the {@code key} with the given {@code result}.
+ * Associates the {@code key} with the provided {@code result}.
*
* <p>Any previous mapping for a key, whether success or failure, is deleted.
+ *
+ * @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder<KeyType, ValueType> setResult(
@@ -209,7 +227,11 @@
return this;
}
- /** Builds an {@link AppSearchBatchResult} from the contents of this {@link Builder}. */
+ /**
+ * Builds an {@link AppSearchBatchResult} object from the contents of this {@link Builder}.
+ *
+ * @throws IllegalStateException if the builder has already been used.
+ */
@NonNull
public AppSearchBatchResult<KeyType, ValueType> build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
index 69d4e53..6a5975e 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java
@@ -36,12 +36,89 @@
import java.util.function.Consumer;
/**
- * This class provides access to the centralized AppSearch index maintained by the system.
+ * Provides access to the centralized AppSearch index maintained by the system.
*
- * <p>Apps can index structured text documents with AppSearch, which can then be retrieved through
- * the query API.
+ * <p>AppSearch is a search library for managing structured data featuring:
+ * <ul>
+ * <li>A fully offline on-device solution
+ * <li>A set of APIs for applications to index documents and retrieve them via full-text search
+ * <li>APIs for applications to allow the System to display their content on system UI surfaces
+ * <li>Similarly, APIs for applications to allow the System to share their content with other
+ * specified applications.
+ * </ul>
+ *
+ * <p>Applications create a database by opening an {@link AppSearchSession}.
+ *
+ * <p>Example:
+ * <pre>
+ * AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class);
+ *
+ * AppSearchManager.SearchContext searchContext = new AppSearchManager.SearchContext.Builder().
+ * setDatabaseName(dbName).build());
+ * appSearchManager.createSearchSession(searchContext, mExecutor, appSearchSessionResult -> {
+ * mAppSearchSession = appSearchSessionResult.getResultValue();
+ * });</pre>
+ *
+ * <p>After opening the session, a schema must be set in order to define the organizational
+ * structure of data. The schema is set by calling {@link AppSearchSession#setSchema}. The schema
+ * is composed of a collection of {@link AppSearchSchema} objects, each of which defines a unique
+ * type of data.
+ *
+ * <p>Example:
+ * <pre>
+ * AppSearchSchema emailSchemaType = new AppSearchSchema.Builder("Email")
+ * .addProperty(new StringPropertyConfig.Builder("subject")
+ * .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ * .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ * .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ * .build()
+ * ).build();
+ *
+ * SetSchemaRequest request = new SetSchemaRequest.Builder().addSchema(emailSchemaType).build();
+ * mAppSearchSession.set(request, mExecutor, appSearchResult -> {
+ * if (appSearchResult.isSuccess()) {
+ * //Schema has been successfully set.
+ * }
+ * });</pre>
+ *
+ * <p>The basic unit of data in AppSearch is represented as a {@link GenericDocument} object,
+ * containing a URI, namespace, time-to-live, score, and properties. A namespace organizes a
+ * logical group of documents. For example, a namespace can be created to group documents on a
+ * per-account basis. A URI identifies a single document within a namespace. The combination
+ * of URI and namespace uniquely identifies a {@link GenericDocument} in the database.
+ *
+ * <p>Once the schema has been set, {@link GenericDocument} objects can be put into the database
+ * and indexed by calling {@link AppSearchSession#put}.
+ *
+ * <p>Example:
+ * <pre>
+ * // Although for this example we use GenericDocument directly, we recommend extending
+ * // GenericDocument to create specific types (i.e. Email) with specific setters/getters.
+ * GenericDocument email = new GenericDocument.Builder<>(URI, EMAIL_SCHEMA_TYPE)
+ * .setNamespace(NAMESPACE)
+ * .setPropertyString(“subject”, EMAIL_SUBJECT)
+ * .setScore(EMAIL_SCORE)
+ * .build();
+ *
+ * PutDocumentsRequest request = new PutDocumentsRequest.Builder().addGenericDocuments(email)
+ * .build();
+ * mAppSearchSession.put(request, mExecutor, appSearchBatchResult -> {
+ * if (appSearchBatchResult.isSuccess()) {
+ * //All documents have been successfully indexed.
+ * }
+ * });</pre>
+ *
+ * <p>Searching within the database is done by calling {@link AppSearchSession#search} and providing
+ * the query string to search for, as well as a {@link SearchSpec}.
+ *
+ * <p>Alternatively, {@link AppSearchSession#getByUri} can be called to retrieve documents by URI
+ * and namespace.
+ *
+ * <p>Document removal is done either by time-to-live expiration, or explicitly calling a remove
+ * operation. Remove operations can be done by URI and namespace via
+ * {@link AppSearchSession#remove(RemoveByUriRequest, Executor, BatchResultCallback)},
+ * or by query via {@link AppSearchSession#remove(String, SearchSpec, Executor, Consumer)}.
*/
-// TODO(b/148046169): This class header needs a detailed example/tutorial.
@SystemService(Context.APP_SEARCH_SERVICE)
public class AppSearchManager {
/**
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index 3c02d10..54f3350 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -41,7 +41,7 @@
* Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be
* placed and queried.
*
- * This class is thread safe.
+ * <p>This class is thread safe.
*/
public final class AppSearchSession implements Closeable {
private static final String TAG = "AppSearchSession";
@@ -102,92 +102,23 @@
}
/**
- * Sets the schema that will be used by documents provided to the {@link #put} method.
+ * Sets the schema that represents the organizational structure of data within the AppSearch
+ * database.
*
- * <p>The schema provided here is compared to the stored copy of the schema previously supplied
- * to {@link #setSchema}, if any, to determine how to treat existing documents. The following
- * types of schema modifications are always safe and are made without deleting any existing
- * documents:
+ * <p>Upon creating an {@link AppSearchSession}, {@link #setSchema} should be called. If the
+ * schema needs to be updated, or it has not been previously set, then the provided schema will
+ * be saved and persisted to disk. Otherwise, {@link #setSchema} is handled efficiently as a
+ * no-op call.
*
- * <ul>
- * <li>Addition of new types
- * <li>Addition of new {@link AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} or
- * {@link AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} properties to a
- * type
- * <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an {@link
- * AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link
- * AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} property.
- * </ul>
- *
- * <p>The following types of schema changes are not backwards-compatible:
- *
- * <ul>
- * <li>Removal of an existing type
- * <li>Removal of a property from a type
- * <li>Changing the data type ({@code boolean}, {@code long}, etc.) of an existing property
- * <li>For properties of {@code Document} type, changing the schema type of {@code Document}s
- * of that property
- * <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an {@link
- * AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link
- * AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property).
- * <li>Adding a {@link AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property.
- * </ul>
- *
- * <p>Supplying a schema with such changes will, by default, result in this call completing its
- * future with an {@link android.app.appsearch.exceptions.AppSearchException} with a code of
- * {@link AppSearchResult#RESULT_INVALID_SCHEMA} and a message describing the incompatibility.
- * In this case the previously set schema will remain active.
- *
- * <p>If you need to make non-backwards-compatible changes as described above, you can either:
- *
- * <ul>
- * <li>Set the {@link SetSchemaRequest.Builder#setForceOverride} method to {@code true}. In
- * this case, instead of completing its future with an {@link
- * android.app.appsearch.exceptions.AppSearchException} with the {@link
- * AppSearchResult#RESULT_INVALID_SCHEMA} error code, all documents which are not
- * compatible with the new schema will be deleted and the incompatible schema will be
- * applied. Incompatible types and deleted types will be set into {@link
- * SetSchemaResponse#getIncompatibleTypes()} and {@link
- * SetSchemaResponse#getDeletedTypes()}, respectively.
- * <li>Add a {@link android.app.appsearch.AppSearchSchema.Migrator} for each incompatible type
- * and make no deletion. The migrator will migrate documents from it's old schema version
- * to the new version. Migrated types will be set into both {@link
- * SetSchemaResponse#getIncompatibleTypes()} and {@link
- * SetSchemaResponse#getMigratedTypes()}. See the migration section below.
- * </ul>
- *
- * <p>It is a no-op to set the same schema as has been previously set; this is handled
- * efficiently.
- *
- * <p>By default, documents are visible on platform surfaces. To opt out, call {@code
- * SetSchemaRequest.Builder#setPlatformSurfaceable} with {@code surfaceable} as false. Any
- * visibility settings apply only to the schemas that are included in the {@code request}.
- * Visibility settings for a schema type do not apply or persist across {@link
- * SetSchemaRequest}s.
- *
- * <p>Migration: make non-backwards-compatible changes will delete all stored documents in old
- * schema. You can save your documents by setting {@link
- * android.app.appsearch.AppSearchSchema.Migrator} via the {@link
- * SetSchemaRequest.Builder#setMigrator} for each type you want to save.
- *
- * <p>{@link android.app.appsearch.AppSearchSchema.Migrator#onDowngrade} or {@link
- * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} will be triggered if the version
- * number of the schema stored in AppSearch is different with the version in the request.
- *
- * <p>If any error or Exception occurred in the {@link
- * android.app.appsearch.AppSearchSchema.Migrator#onDowngrade}, {@link
- * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} or {@link
- * android.app.appsearch.AppSearchMigrationHelper.Transformer#transform}, the migration will be
- * terminated, the setSchema request will be rejected unless the schema changes are
- * backwards-compatible, and stored documents won't have any observable changes.
- *
- * @param request The schema update request.
+ * @param request the schema to set or update the AppSearch database to.
* @param executor Executor on which to invoke the callback.
* @param callback Callback to receive errors resulting from setting the schema. If the
* operation succeeds, the callback will be invoked with {@code null}.
* @see android.app.appsearch.AppSearchSchema.Migrator
* @see android.app.appsearch.AppSearchMigrationHelper.Transformer
*/
+ // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
+ // exposed.
public void setSchema(
@NonNull SetSchemaRequest request,
@NonNull @CallbackExecutor Executor executor,
@@ -280,12 +211,13 @@
}
/**
- * Indexes documents into AppSearch.
+ * Indexes documents into the {@link AppSearchSession} database.
*
- * <p>Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a
- * schema type previously registered via the {@link #setSchema} method.
+ * <p>Each {@link GenericDocument} object must have a {@code schemaType} field set to an {@link
+ * AppSearchSchema} type that has been previously registered by calling the {@link #setSchema}
+ * method.
*
- * @param request {@link PutDocumentsRequest} containing documents to be indexed
+ * @param request containing documents to be indexed.
* @param executor Executor on which to invoke the callback.
* @param callback Callback to receive pending result of performing this operation. The keys
* of the returned {@link AppSearchBatchResult} are the URIs of the input
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
index 09bca4f..93b102b 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
@@ -98,8 +98,7 @@
* <p>Document access can also be granted to system UIs by specifying {@link
* SetSchemaRequest.Builder#setSchemaTypeVisibilityForSystemUi} when building a schema.
*
- * <p>See {@link AppSearchSession#search} for a detailed explanation on
- * forming a query string.
+ * <p>See {@link AppSearchSession#search} for a detailed explanation on forming a query string.
*
* <p>This method is lightweight. The heavy work will be done in {@link
* SearchResults#getNextPage}.
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
index a63e015..e9e978e 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
@@ -33,12 +33,16 @@
import java.util.function.Consumer;
/**
- * SearchResults are a returned object from a query API.
+ * Encapsulates results of a search operation.
*
- * <p>Each {@link SearchResult} contains a document and may contain other fields like snippets based
- * on request.
+ * <p>Each {@link AppSearchSession#search} operation returns a list of {@link SearchResult} objects,
+ * referred to as a "page", limited by the size configured by {@link
+ * SearchSpec.Builder#setResultCountPerPage}.
*
- * <p>Should close this object after finish fetching results.
+ * <p>To fetch a page of results, call {@link #getNextPage}.
+ *
+ * <p>All instances of {@link SearchResults} must call {@link SearchResults#close()} after the
+ * results are fetched.
*
* <p>This class is not thread safe.
*/
@@ -87,12 +91,12 @@
}
/**
- * Gets a whole page of {@link SearchResult}s.
+ * Retrieves the next page of {@link SearchResult} objects.
*
- * <p>Re-call this method to get next page of {@link SearchResult}, until it returns an empty
- * list.
+ * <p>The page size is configured by {@link SearchSpec.Builder#setResultCountPerPage}.
*
- * <p>The page size is set by {@link SearchSpec.Builder#setResultCountPerPage}.
+ * <p>Continue calling this method to access results until it returns an empty list, signifying
+ * there are no more results.
*
* @param callback Callback to receive the pending result of performing this operation.
*/
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 57700f8..01473be 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/PutDocumentsRequest.java
@@ -30,8 +30,6 @@
/**
* Encapsulates a request to index documents into an {@link AppSearchSession} database.
*
- * <p>@see AppSearchSession#putDocuments
- *
* @see AppSearchSession#put
*/
public final class PutDocumentsRequest {
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
index 2caa94a5e..426a903 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
@@ -32,6 +32,41 @@
/**
* Encapsulates a request to update the schema of an {@link AppSearchSession} database.
*
+ * <p>The schema is composed of a collection of {@link AppSearchSchema} objects, each of which
+ * defines a unique type of data.
+ *
+ * <p>The first call to SetSchemaRequest will set the provided schema and store it within the {@link
+ * AppSearchSession} database.
+ *
+ * <p>Subsequent calls will compare the provided schema to the previously saved schema, to determine
+ * how to treat existing documents.
+ *
+ * <p>The following types of schema modifications are always safe and are made without deleting any
+ * existing documents:
+ *
+ * <ul>
+ * <li>Addition of new {@link AppSearchSchema} types
+ * <li>Addition of new properties to an existing {@link AppSearchSchema} type
+ * <li>Changing the cardinality of a property to be less restrictive
+ * </ul>
+ *
+ * <p>The following types of schema changes are not backwards compatible:
+ *
+ * <ul>
+ * <li>Removal of an existing {@link AppSearchSchema} type
+ * <li>Removal of a property from an existing {@link AppSearchSchema} type
+ * <li>Changing the data type of an existing property
+ * <li>Changing the cardinality of a property to be more restrictive
+ * </ul>
+ *
+ * <p>Providing a schema with incompatible changes, will throw an {@link
+ * android.app.appsearch.exceptions.AppSearchException}, with a message describing the
+ * incompatibility. As a result, the previously set schema will remain unchanged.
+ *
+ * <p>Backward incompatible changes can be made by setting {@link
+ * SetSchemaRequest.Builder#setForceOverride} method to {@code true}. This deletes all documents
+ * that are incompatible with the new schema. The new schema is then saved and persisted to disk.
+ *
* @see AppSearchSession#setSchema
*/
public final class SetSchemaRequest {
@@ -54,14 +89,15 @@
mForceOverride = forceOverride;
}
- /** Returns the schemas that are part of this request. */
+ /** Returns the {@link AppSearchSchema} types that are part of this request. */
@NonNull
public Set<AppSearchSchema> getSchemas() {
return Collections.unmodifiableSet(mSchemas);
}
/**
- * Returns the set of schema types that have opted out of being visible on system UI surfaces.
+ * Returns all the schema types that are opted out of being displayed and visible on any system
+ * UI surface.
*/
@NonNull
public Set<String> getSchemasNotVisibleToSystemUi() {
@@ -70,10 +106,9 @@
/**
* Returns a mapping of schema types to the set of packages that have access to that schema
- * type. Each package is represented by a {@link PackageIdentifier}. name and byte[]
- * certificate.
+ * type.
*
- * <p>This method is inefficient to call repeatedly.
+ * <p>It’s inefficient to call this method repeatedly.
*/
@NonNull
public Map<String, Set<PackageIdentifier>> getSchemasVisibleToPackages() {
@@ -91,9 +126,8 @@
}
/**
- * Returns a mapping of schema types to the set of packages that have access to that schema
- * type. Each package is represented by a {@link PackageIdentifier}. name and byte[]
- * certificate.
+ * Returns a mapping of {@link AppSearchSchema} types to the set of packages that have access to
+ * that schema type.
*
* <p>A more efficient version of {@link #getSchemasVisibleToPackages}, but it returns a
* modifiable map. This is not meant to be unhidden and should only be used by internal classes.
@@ -110,7 +144,11 @@
return mForceOverride;
}
- /** Builder for {@link SetSchemaRequest} objects. */
+ /**
+ * Builder for {@link SetSchemaRequest} objects.
+ *
+ * <p>Once {@link #build} is called, the instance can no longer be used.
+ */
public static final class Builder {
private final Set<AppSearchSchema> mSchemas = new ArraySet<>();
private final Set<String> mSchemasNotVisibleToSystemUi = new ArraySet<>();
@@ -121,9 +159,11 @@
private boolean mBuilt = false;
/**
- * Adds one or more types to the schema.
+ * Adds one or more {@link AppSearchSchema} types to the schema.
*
- * <p>Any documents of these types will be visible on system UI surfaces by default.
+ * <p>An {@link AppSearchSchema} object represents one type of structured data.
+ *
+ * @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder addSchemas(@NonNull AppSearchSchema... schemas) {
@@ -132,9 +172,11 @@
}
/**
- * Adds one or more types to the schema.
+ * Adds a collection of {@link AppSearchSchema} objects to the schema.
*
- * <p>Any documents of these types will be visible on system UI surfaces by default.
+ * <p>An {@link AppSearchSchema} object represents one type of structured data.
+ *
+ * @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder addSchemas(@NonNull Collection<AppSearchSchema> schemas) {
@@ -145,10 +187,17 @@
}
/**
- * Sets visibility on system UI surfaces for the given {@code schemaType}.
+ * Sets whether or not documents from the provided {@code schemaType} will be displayed and
+ * visible on any system UI surface.
+ *
+ * <p>This setting applies to the provided {@code schemaType} only, and does not persist
+ * across {@link AppSearchSession#setSchema} calls.
+ *
+ * <p>By default, documents are displayed and visible on system UI surfaces.
*
* @param schemaType The schema type to set visibility on.
* @param visible Whether the {@code schemaType} will be visible or not.
+ * @throws IllegalStateException if the builder has already been used.
*/
// Merged list available from getSchemasNotVisibleToSystemUi
@SuppressLint("MissingGetterMatchingBuilder")
@@ -167,11 +216,25 @@
}
/**
- * Sets visibility for a package for the given {@code schemaType}.
+ * Sets whether or not documents from the provided {@code schemaType} can be read by the
+ * specified package.
+ *
+ * <p>Each package is represented by a {@link PackageIdentifier}, containing a package name
+ * and a byte array of type {@link android.content.pm.PackageManager#CERT_INPUT_SHA256}.
+ *
+ * <p>To opt into one-way data sharing with another application, the developer will need to
+ * explicitly grant the other application’s package name and certificate Read access to its
+ * data.
+ *
+ * <p>For two-way data sharing, both applications need to explicitly grant Read access to
+ * one another.
+ *
+ * <p>By default, data sharing between applications is disabled.
*
* @param schemaType The schema type to set visibility on.
* @param visible Whether the {@code schemaType} will be visible or not.
* @param packageIdentifier Represents the package that will be granted visibility.
+ * @throws IllegalStateException if the builder has already been used.
*/
// Merged list available from getSchemasVisibleToPackages
@SuppressLint("MissingGetterMatchingBuilder")
@@ -224,13 +287,15 @@
}
/**
- * Configures the {@link SetSchemaRequest} to delete any existing documents that don't
- * follow the new schema.
+ * Sets whether or not to override the current schema in the {@link AppSearchSession}
+ * database.
*
- * <p>By default, this is {@code false} and schema incompatibility causes the {@link
- * AppSearchSession#setSchema} call to fail.
+ * <p>Call this method whenever backward incompatible changes need to be made by setting
+ * {@code forceOverride} to {@code true}. As a result, during execution of the setSchema
+ * operation, all documents that are incompatible with the new schema will be deleted and
+ * the new schema will be saved and persisted.
*
- * @see AppSearchSession#setSchema
+ * <p>By default, this is {@code false}.
*/
@NonNull
public Builder setForceOverride(boolean forceOverride) {
@@ -239,10 +304,11 @@
}
/**
- * Builds a new {@link SetSchemaRequest}.
+ * Builds a new {@link SetSchemaRequest} object.
*
- * @throws IllegalArgumentException If schema types were referenced, but the corresponding
- * {@link AppSearchSchema} was never added.
+ * @throws IllegalArgumentException if schema types were referenced, but the corresponding
+ * {@link AppSearchSchema} type was never added.
+ * @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public SetSchemaRequest build() {
diff --git a/apex/appsearch/service/Android.bp b/apex/appsearch/service/Android.bp
index 2fd5c73..57ee1ec 100644
--- a/apex/appsearch/service/Android.bp
+++ b/apex/appsearch/service/Android.bp
@@ -11,6 +11,15 @@
// WITHOUT 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_library {
name: "service-appsearch",
installable: true,
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 6c2e30e..e2c211b 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
@@ -654,6 +654,35 @@
}
}
+ /**
+ * Returns a mapping of package names to all the databases owned by that package.
+ *
+ * <p>This method is inefficient to call repeatedly.
+ */
+ @NonNull
+ public Map<String, Set<String>> getPackageToDatabases() {
+ mReadWriteLock.readLock().lock();
+ try {
+ Map<String, Set<String>> packageToDatabases = new ArrayMap<>();
+ for (String prefix : mSchemaMapLocked.keySet()) {
+ String packageName = getPackageName(prefix);
+
+ Set<String> databases = packageToDatabases.get(packageName);
+ if (databases == null) {
+ databases = new ArraySet<>();
+ packageToDatabases.put(packageName, databases);
+ }
+
+ String databaseName = getDatabaseName(prefix);
+ databases.add(databaseName);
+ }
+
+ return packageToDatabases;
+ } finally {
+ mReadWriteLock.readLock().unlock();
+ }
+ }
+
@GuardedBy("mReadWriteLock")
private SearchResultPage doQueryLocked(
@NonNull Set<String> prefixes,
@@ -1211,26 +1240,8 @@
return schemaProto.getSchema();
}
- /**
- * Returns true if the {@code packageName} and {@code databaseName} has the {@code schemaType}
- */
- @GuardedBy("mReadWriteLock")
- boolean hasSchemaTypeLocked(
- @NonNull String packageName, @NonNull String databaseName, @NonNull String schemaType) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkNotNull(databaseName);
- Preconditions.checkNotNull(schemaType);
-
- String prefix = createPrefix(packageName, databaseName);
- Set<String> schemaTypes = mSchemaMapLocked.get(prefix);
- if (schemaTypes == null) {
- return false;
- }
-
- return schemaTypes.contains(prefix + schemaType);
- }
-
/** Returns a set of all prefixes AppSearchImpl knows about. */
+ // TODO(b/180058203): Remove this method once platform has switched away from using this method.
@GuardedBy("mReadWriteLock")
@NonNull
Set<String> getPrefixesLocked() {
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index fc0299e..2c9477a 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-I895f5fb3bcb4be0642c6193000e57d80aafe2166
+I593dfd22279739e5f578e07d36a55cf02ee942c5
diff --git a/apex/appsearch/testing/Android.bp b/apex/appsearch/testing/Android.bp
index 54d5039..eb072af 100644
--- a/apex/appsearch/testing/Android.bp
+++ b/apex/appsearch/testing/Android.bp
@@ -11,6 +11,15 @@
// WITHOUT 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_library {
name: "AppSearchTestUtils",
srcs: ["java/**/*.java"],
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
index 34c7ccb..1428fb1 100644
--- a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchSessionShim.java
@@ -33,90 +33,16 @@
public interface AppSearchSessionShim extends Closeable {
/**
- * Sets the schema that will be used by documents provided to the {@link #put} method.
+ * Sets the schema that represents the organizational structure of data within the AppSearch
+ * database.
*
- * <p>The schema provided here is compared to the stored copy of the schema previously supplied
- * to {@link #setSchema}, if any, to determine how to treat existing documents. The following
- * types of schema modifications are always safe and are made without deleting any existing
- * documents:
+ * <p>Upon creating an {@link AppSearchSessionShim}, {@link #setSchema} should be called. If the
+ * schema needs to be updated, or it has not been previously set, then the provided schema will
+ * be saved and persisted to disk. Otherwise, {@link #setSchema} is handled efficiently as a
+ * no-op call.
*
- * <ul>
- * <li>Addition of new types
- * <li>Addition of new {@link AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} or
- * {@link AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} properties to a
- * type
- * <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an {@link
- * AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link
- * AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED} property.
- * </ul>
- *
- * <p>The following types of schema changes are not backwards-compatible:
- *
- * <ul>
- * <li>Removal of an existing type
- * <li>Removal of a property from a type
- * <li>Changing the data type ({@code boolean}, {@code long}, etc.) of an existing property
- * <li>For properties of {@code Document} type, changing the schema type of {@code Document}s
- * of that property
- * <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an {@link
- * AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} property into a {@link
- * AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property).
- * <li>Adding a {@link AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED} property.
- * </ul>
- *
- * <p>Supplying a schema with such changes will, by default, result in this call completing its
- * future with an {@link android.app.appsearch.exceptions.AppSearchException} with a code of
- * {@link AppSearchResult#RESULT_INVALID_SCHEMA} and a message describing the incompatibility.
- * In this case the previously set schema will remain active.
- *
- * <p>If you need to make non-backwards-compatible changes as described above, you can either:
- *
- * <ul>
- * <li>Set the {@link SetSchemaRequest.Builder#setForceOverride} method to {@code true}. In
- * this case, instead of completing its future with an {@link
- * android.app.appsearch.exceptions.AppSearchException} with the {@link
- * AppSearchResult#RESULT_INVALID_SCHEMA} error code, all documents which are not
- * compatible with the new schema will be deleted and the incompatible schema will be
- * applied. Incompatible types and deleted types will be set into {@link
- * SetSchemaResponse#getIncompatibleTypes()} and {@link
- * SetSchemaResponse#getDeletedTypes()}, respectively.
- * <li>Add a {@link android.app.appsearch.AppSearchSchema.Migrator} for each incompatible type
- * and make no deletion. The migrator will migrate documents from it's old schema version
- * to the new version. Migrated types will be set into both {@link
- * SetSchemaResponse#getIncompatibleTypes()} and {@link
- * SetSchemaResponse#getMigratedTypes()}. See the migration section below.
- * </ul>
- *
- * <p>It is a no-op to set the same schema as has been previously set; this is handled
- * efficiently.
- *
- * <p>By default, documents are visible on platform surfaces. To opt out, call {@code
- * SetSchemaRequest.Builder#setPlatformSurfaceable} with {@code surfaceable} as false. Any
- * visibility settings apply only to the schemas that are included in the {@code request}.
- * Visibility settings for a schema type do not apply or persist across {@link
- * SetSchemaRequest}s.
- *
- * <p>Migration: make non-backwards-compatible changes will delete all stored documents in old
- * schema. You can save your documents by setting {@link
- * android.app.appsearch.AppSearchSchema.Migrator} via the {@link
- * SetSchemaRequest.Builder#setMigrator} for each type you want to save.
- *
- * <p>{@link android.app.appsearch.AppSearchSchema.Migrator#onDowngrade} or {@link
- * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} will be triggered if the version
- * number of the schema stored in AppSearch is different with the version in the request.
- *
- * <p>If any error or Exception occurred in the {@link
- * android.app.appsearch.AppSearchSchema.Migrator#onDowngrade}, {@link
- * android.app.appsearch.AppSearchSchema.Migrator#onUpgrade} or {@link
- * android.app.appsearch.AppSearchMigrationHelper.Transformer#transform}, the migration will be
- * terminated, the setSchema request will be rejected unless the schema changes are
- * backwards-compatible, and stored documents won't have any observable changes.
- *
- * @param request The schema update request.
- * @return A {@link ListenableFuture} with exception if we hit any error. Or the pending {@link
- * SetSchemaResponse} of performing this operation, if the schema has been successfully set.
- * @see android.app.appsearch.AppSearchSchema.Migrator
- * @see android.app.appsearch.AppSearchMigrationHelper.Transformer
+ * @param request the schema to set or update the AppSearch database to.
+ * @return a {@link ListenableFuture} which resolves to a {@link SetSchemaResponse} object.
*/
// TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
// exposed.
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index 7c7b210..77146e0 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -23,7 +23,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.compat.annotation.ChangeId;
-import android.compat.annotation.Disabled;
+import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -202,7 +202,7 @@
* @hide
*/
@ChangeId
- @Disabled // TODO (b/171306433): Enable starting S.
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
public static final long REQUIRE_EXACT_ALARM_PERMISSION = 171306433L;
@UnsupportedAppUsage
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 559a434..ea73369 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -423,6 +423,8 @@
static final String KEY_ALLOW_WHILE_IDLE_COMPAT_QUOTA = "allow_while_idle_compat_quota";
private static final String KEY_ALLOW_WHILE_IDLE_WINDOW = "allow_while_idle_window";
+ private static final String KEY_CRASH_NON_CLOCK_APPS = "crash_non_clock_apps";
+
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS;
@@ -454,6 +456,8 @@
private static final int DEFAULT_ALLOW_WHILE_IDLE_QUOTA = 72;
private static final long DEFAULT_ALLOW_WHILE_IDLE_WINDOW = 60 * 60 * 1000; // 1 hour.
+ // TODO (b/171306433): Change to true by default.
+ private static final boolean DEFAULT_CRASH_NON_CLOCK_APPS = false;
// Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -495,6 +499,13 @@
*/
public long ALLOW_WHILE_IDLE_WINDOW = DEFAULT_ALLOW_WHILE_IDLE_WINDOW;
+ /**
+ * Whether or not to crash callers that use setExactAndAllowWhileIdle or setAlarmClock
+ * but don't hold the required permission. This is useful to catch broken
+ * apps and reverting to a softer failure in case of broken apps.
+ */
+ public boolean CRASH_NON_CLOCK_APPS = DEFAULT_CRASH_NON_CLOCK_APPS;
+
private long mLastAllowWhileIdleWhitelistDuration = -1;
Constants() {
@@ -607,6 +618,10 @@
KEY_TIME_TICK_ALLOWED_WHILE_IDLE,
DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE);
break;
+ case KEY_CRASH_NON_CLOCK_APPS:
+ CRASH_NON_CLOCK_APPS = properties.getBoolean(KEY_CRASH_NON_CLOCK_APPS,
+ DEFAULT_CRASH_NON_CLOCK_APPS);
+ break;
default:
if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
// The quotas need to be updated in order, so we can't just rely
@@ -741,6 +756,9 @@
pw.print(KEY_TIME_TICK_ALLOWED_WHILE_IDLE, TIME_TICK_ALLOWED_WHILE_IDLE);
pw.println();
+ pw.print(KEY_CRASH_NON_CLOCK_APPS, CRASH_NON_CLOCK_APPS);
+ pw.println();
+
pw.decreaseIndent();
}
@@ -1914,11 +1932,12 @@
}
/**
- * Returns true if the given uid is on the system or user's power save exclusion list.
+ * Returns true if the given uid does not require SCHEDULE_EXACT_ALARM to set exact,
+ * allow-while-idle alarms.
*/
- boolean isWhitelisted(int uid) {
- return (mLocalDeviceIdleController == null || mLocalDeviceIdleController.isAppOnWhitelist(
- UserHandle.getAppId(uid)));
+ boolean isExemptFromPermission(int uid) {
+ return (UserHandle.isSameApp(mSystemUiUid, uid) || mLocalDeviceIdleController == null
+ || mLocalDeviceIdleController.isAppOnWhitelist(UserHandle.getAppId(uid)));
}
/**
@@ -1949,7 +1968,7 @@
if (windowLength != AlarmManager.WINDOW_EXACT) {
needsPermission = false;
lowQuota = true;
- idleOptions = isWhitelisted(callingUid) ? mOptsWithFgs.toBundle()
+ idleOptions = isExemptFromPermission(callingUid) ? mOptsWithFgs.toBundle()
: mOptsWithoutFgs.toBundle();
} else if (alarmClock != null) {
needsPermission = true;
@@ -1966,16 +1985,22 @@
idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null;
}
if (needsPermission && !canScheduleExactAlarms()) {
- if (alarmClock == null && isWhitelisted(callingUid)) {
+ if (alarmClock == null && isExemptFromPermission(callingUid)) {
// If the app is on the full system allow-list (not except-idle), we still
// allow the alarms, but with a lower quota to keep pre-S compatibility.
lowQuota = true;
} else {
- final String errorMessage = "Caller needs to hold "
+ final String errorMessage = "Caller " + callingPackage + " needs to hold "
+ Manifest.permission.SCHEDULE_EXACT_ALARM + " to set "
+ ((allowWhileIdle) ? "exact, allow-while-idle" : "alarm-clock")
+ " alarms.";
- throw new SecurityException(errorMessage);
+ if (mConstants.CRASH_NON_CLOCK_APPS) {
+ throw new SecurityException(errorMessage);
+ } else {
+ Slog.wtf(TAG, errorMessage);
+ idleOptions = mOptsWithoutFgs.toBundle();
+ lowQuota = allowWhileIdle;
+ }
}
}
if (lowQuota) {
@@ -2933,7 +2958,7 @@
if (UserHandle.isCore(uid) || uid == mSystemUiUid) {
return;
}
- if (isWhitelisted(uid)) {
+ if (isExemptFromPermission(uid)) {
return;
}
if (!CompatChanges.isChangeEnabled(
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 c5d3b7a..040a116 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -53,7 +53,6 @@
import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.Binder;
-import android.os.Build;
import android.os.Handler;
import android.os.LimitExceededException;
import android.os.Looper;
@@ -153,8 +152,7 @@
/** The maximum number of jobs that we allow an unprivileged app to schedule */
private static final int MAX_JOBS_PER_APP = 100;
/** The number of the most recently completed jobs to keep track of for debugging purposes. */
- private static final int NUM_COMPLETED_JOB_HISTORY =
- Build.IS_USERDEBUG || Build.IS_ENG ? 25 : 0;
+ private static final int NUM_COMPLETED_JOB_HISTORY = 20;
@VisibleForTesting
public static Clock sSystemClock = Clock.systemUTC();
@@ -889,8 +887,10 @@
}
@Override
- public void onUserStarting(@NonNull TargetUser user) {
+ public void onUserUnlocked(@NonNull TargetUser user) {
synchronized (mLock) {
+ // Note that the user has started after its unlocked instead of when the user
+ // actually starts because the storage won't be decrypted until unlock.
mStartedUsers = ArrayUtils.appendInt(mStartedUsers, user.getUserIdentifier());
}
// Let's kick any outstanding jobs for this user.
@@ -898,12 +898,6 @@
}
@Override
- public void onUserUnlocking(@NonNull TargetUser user) {
- // Let's kick any outstanding jobs for this user.
- mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
- }
-
- @Override
public void onUserStopping(@NonNull TargetUser user) {
synchronized (mLock) {
mStartedUsers = ArrayUtils.removeInt(mStartedUsers, user.getUserIdentifier());
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 be91947..2a23d60 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -271,7 +271,9 @@
if (job.shouldTreatAsExpeditedJob()) {
// TODO(171305774): The job should run on the little cores. We'll probably need
// another binding flag for that.
- bindFlags = Context.BIND_AUTO_CREATE;
+ bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
+ | Context.BIND_ALMOST_PERCEPTIBLE
+ | Context.BIND_ALLOW_NETWORK_ACCESS;
} 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/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 824fa7f..2faa836 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -828,8 +828,8 @@
}
@NonNull
- private ShrinkableDebits getEJQuotaLocked(final int userId,
- @NonNull final String packageName) {
+ @VisibleForTesting
+ ShrinkableDebits getEJDebitsLocked(final int userId, @NonNull final String packageName) {
ShrinkableDebits debits = mEJStats.get(userId, packageName);
if (debits == null) {
debits = new ShrinkableDebits(
@@ -931,7 +931,7 @@
@VisibleForTesting
long getRemainingEJExecutionTimeLocked(final int userId, @NonNull final String packageName) {
- ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
+ ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
if (quota.getStandbyBucketLocked() == NEVER_INDEX) {
return 0;
}
@@ -948,7 +948,7 @@
if (ts.endTimeElapsed < windowStartTimeElapsed) {
final long duration = ts.endTimeElapsed - ts.startTimeElapsed;
remainingMs += duration;
- quota.transactOnDebitsLocked(-duration);
+ quota.transactLocked(-duration);
timingSessions.remove(0);
} else if (ts.startTimeElapsed < windowStartTimeElapsed) {
remainingMs += windowStartTimeElapsed - ts.startTimeElapsed;
@@ -960,15 +960,16 @@
}
}
+ TopAppTimer topAppTimer = mTopAppTrackers.get(userId, packageName);
+ if (topAppTimer != null && topAppTimer.isActive()) {
+ remainingMs += topAppTimer.getPendingReward(nowElapsed);
+ }
+
Timer timer = mEJPkgTimers.get(userId, packageName);
if (timer == null) {
return remainingMs;
}
- // There's a case where the debits tally is 0 but a currently running HPJ still counts
- // towards quota. If the app gets a reward in this case, the reward is lost and the HPJ
- // run is still fully counted.
- // TODO(171305774)/STOPSHIP: make sure getting rewards while HPJ currently executing isn't
- // treated negatively
+
return remainingMs - timer.getCurrentDuration(sElapsedRealtimeClock.millis());
}
@@ -1081,7 +1082,7 @@
}
final long nowElapsed = sElapsedRealtimeClock.millis();
- ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
+ ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
final long limitMs = getEJLimitMsLocked(packageName, quota.getStandbyBucketLocked());
final long startWindowElapsed = Math.max(0, nowElapsed - mEJLimitWindowSizeMs);
long remainingDeadSpaceMs = remainingExecutionTimeMs;
@@ -1372,6 +1373,11 @@
@VisibleForTesting
void saveTimingSession(final int userId, @NonNull final String packageName,
@NonNull final TimingSession session, boolean isExpedited) {
+ saveTimingSession(userId, packageName, session, isExpedited, 0);
+ }
+
+ private void saveTimingSession(final int userId, @NonNull final String packageName,
+ @NonNull final TimingSession session, boolean isExpedited, long debitAdjustment) {
synchronized (mLock) {
final SparseArrayMap<String, List<TimingSession>> sessionMap =
isExpedited ? mEJTimingSessions : mTimingSessions;
@@ -1382,8 +1388,9 @@
}
sessions.add(session);
if (isExpedited) {
- final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
- quota.transactOnDebitsLocked(session.endTimeElapsed - session.startTimeElapsed);
+ final ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
+ quota.transactLocked(session.endTimeElapsed - session.startTimeElapsed
+ + debitAdjustment);
} else {
// Adding a new session means that the current stats are now incorrect.
invalidateAllExecutionStatsLocked(userId, packageName);
@@ -1396,15 +1403,34 @@
private void grantRewardForInstantEvent(
final int userId, @NonNull final String packageName, final long credit) {
synchronized (mLock) {
- final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
- quota.transactOnDebitsLocked(-credit);
- if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
- userId, packageName)) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ final ShrinkableDebits quota = getEJDebitsLocked(userId, packageName);
+ if (transactQuotaLocked(userId, packageName, nowElapsed, quota, credit)
+ && maybeUpdateConstraintForPkgLocked(nowElapsed, userId, packageName)) {
mStateChangedListener.onControllerStateChanged();
}
}
}
+ private boolean transactQuotaLocked(final int userId, @NonNull final String packageName,
+ final long nowElapsed, @NonNull ShrinkableDebits debits, final long credit) {
+ final long oldTally = debits.getTallyLocked();
+ final long leftover = debits.transactLocked(-credit);
+ if (DEBUG) {
+ Slog.d(TAG, "debits overflowed by " + leftover);
+ }
+ boolean changed = oldTally != debits.getTallyLocked();
+ if (leftover != 0) {
+ // Only adjust timer if its active.
+ final Timer ejTimer = mEJPkgTimers.get(userId, packageName);
+ if (ejTimer != null && ejTimer.isActive()) {
+ ejTimer.updateDebitAdjustment(nowElapsed, leftover);
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
private final class EarliestEndTimeFunctor implements Consumer<List<TimingSession>> {
public long earliestEndElapsed = Long.MAX_VALUE;
@@ -1875,7 +1901,8 @@
}
}
- private static final class ShrinkableDebits {
+ @VisibleForTesting
+ static final class ShrinkableDebits {
/** The amount of quota remaining. Can be negative if limit changes. */
private long mDebitTally;
private int mStandbyBucket;
@@ -1893,8 +1920,11 @@
* Negative if the tally should decrease (therefore increasing available quota);
* or positive if the tally should increase (therefore decreasing available quota).
*/
- void transactOnDebitsLocked(final long amount) {
+ long transactLocked(final long amount) {
+ final long leftover = amount < 0 && Math.abs(amount) > mDebitTally
+ ? mDebitTally + amount : 0;
mDebitTally = Math.max(0, mDebitTally + amount);
+ return leftover;
}
void setStandbyBucketLocked(int standbyBucket) {
@@ -1927,6 +1957,7 @@
private final ArraySet<JobStatus> mRunningBgJobs = new ArraySet<>();
private long mStartTimeElapsed;
private int mBgJobCount;
+ private long mDebitAdjustment;
Timer(int uid, int userId, String packageName, boolean regularJobTimer) {
mPkg = new Package(userId, packageName);
@@ -1957,6 +1988,7 @@
if (mRunningBgJobs.size() == 1) {
// Started tracking the first job.
mStartTimeElapsed = sElapsedRealtimeClock.millis();
+ mDebitAdjustment = 0;
if (mRegularJobTimer) {
// Starting the timer means that all cached execution stats are now
// incorrect.
@@ -1988,6 +2020,11 @@
}
}
+ void updateDebitAdjustment(long nowElapsed, long debit) {
+ // Make sure we don't have a credit larger than the expected session.
+ mDebitAdjustment = Math.max(mDebitAdjustment + debit, mStartTimeElapsed - nowElapsed);
+ }
+
/**
* Stops tracking all jobs and cancels any pending alarms. This should only be called if
* the Timer is not going to be used anymore.
@@ -2003,7 +2040,8 @@
return;
}
TimingSession ts = new TimingSession(mStartTimeElapsed, nowElapsed, mBgJobCount);
- saveTimingSession(mPkg.userId, mPkg.packageName, ts, !mRegularJobTimer);
+ saveTimingSession(mPkg.userId, mPkg.packageName, ts, !mRegularJobTimer,
+ mDebitAdjustment);
mBgJobCount = 0;
// Don't reset the tracked jobs list as we need to keep tracking the current number
// of jobs.
@@ -2030,7 +2068,7 @@
long getCurrentDuration(long nowElapsed) {
synchronized (mLock) {
- return !isActive() ? 0 : nowElapsed - mStartTimeElapsed;
+ return !isActive() ? 0 : nowElapsed - mStartTimeElapsed + mDebitAdjustment;
}
}
@@ -2059,6 +2097,7 @@
// Start timing from unplug.
if (mRunningBgJobs.size() > 0) {
mStartTimeElapsed = nowElapsed;
+ mDebitAdjustment = 0;
// NOTE: this does have the unfortunate consequence that if the device is
// repeatedly plugged in and unplugged, or an app changes foreground state
// very frequently, the job count for a package may be artificially high.
@@ -2128,6 +2167,11 @@
pw.print(", ");
pw.print(mBgJobCount);
pw.print(" running bg jobs");
+ if (!mRegularJobTimer) {
+ pw.print(" (debit adj=");
+ pw.print(mDebitAdjustment);
+ pw.print(")");
+ }
pw.println();
pw.increaseIndent();
for (int i = 0; i < mRunningBgJobs.size(); i++) {
@@ -2171,6 +2215,21 @@
mPkg = new Package(userId, packageName);
}
+ private int calculateTimeChunks(final long nowElapsed) {
+ final long totalTopTimeMs = nowElapsed - mStartTimeElapsed;
+ int numTimeChunks = (int) (totalTopTimeMs / mEJTopAppTimeChunkSizeMs);
+ final long remainderMs = totalTopTimeMs % mEJTopAppTimeChunkSizeMs;
+ if (remainderMs >= SECOND_IN_MILLIS) {
+ // "Round up"
+ numTimeChunks++;
+ }
+ return numTimeChunks;
+ }
+
+ long getPendingReward(final long nowElapsed) {
+ return mEJRewardTopAppMs * calculateTimeChunks(nowElapsed);
+ }
+
void processEventLocked(@NonNull UsageEvents.Event event) {
final long nowElapsed = sElapsedRealtimeClock.millis();
switch (event.getEventType()) {
@@ -2186,21 +2245,16 @@
final UsageEvents.Event existingEvent =
mActivities.removeReturnOld(event.mInstanceId);
if (existingEvent != null && mActivities.size() == 0) {
- final long totalTopTimeMs = nowElapsed - mStartTimeElapsed;
- int numTimeChunks = (int) (totalTopTimeMs / mEJTopAppTimeChunkSizeMs);
- final long remainderMs = totalTopTimeMs % mEJTopAppTimeChunkSizeMs;
- if (remainderMs >= SECOND_IN_MILLIS) {
- // "Round up"
- numTimeChunks++;
- }
+ final long pendingReward = getPendingReward(nowElapsed);
if (DEBUG) {
- Slog.d(TAG,
- "Crediting " + mPkg + " for " + numTimeChunks + " time chunks");
+ Slog.d(TAG, "Crediting " + mPkg + " " + pendingReward + "ms"
+ + " for " + calculateTimeChunks(nowElapsed) + " time chunks");
}
- final ShrinkableDebits quota =
- getEJQuotaLocked(mPkg.userId, mPkg.packageName);
- quota.transactOnDebitsLocked(-mEJRewardTopAppMs * numTimeChunks);
- if (maybeUpdateConstraintForPkgLocked(nowElapsed,
+ final ShrinkableDebits debits =
+ getEJDebitsLocked(mPkg.userId, mPkg.packageName);
+ if (transactQuotaLocked(mPkg.userId, mPkg.packageName,
+ nowElapsed, debits, pendingReward)
+ && maybeUpdateConstraintForPkgLocked(nowElapsed,
mPkg.userId, mPkg.packageName)) {
mStateChangedListener.onControllerStateChanged();
}
@@ -2321,7 +2375,7 @@
*/
@Override
public void onUsageEvent(int userId, @NonNull UsageEvents.Event event) {
- mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event);
+ mHandler.obtainMessage(MSG_PROCESS_USAGE_EVENT, userId, 0, event).sendToTarget();
}
}
@@ -2408,7 +2462,6 @@
}
private class QcHandler extends Handler {
- private boolean mIsProcessing;
QcHandler(Looper looper) {
super(looper);
@@ -2417,8 +2470,6 @@
@Override
public void handleMessage(Message msg) {
synchronized (mLock) {
- mIsProcessing = true;
-
switch (msg.what) {
case MSG_REACHED_QUOTA: {
Package pkg = (Package) msg.obj;
@@ -2539,6 +2590,10 @@
final int userId = msg.arg1;
final UsageEvents.Event event = (UsageEvents.Event) msg.obj;
final String pkgName = event.getPackageName();
+ if (DEBUG) {
+ Slog.d(TAG, "Processing event " + event.getEventType()
+ + " for " + string(userId, pkgName));
+ }
switch (event.getEventType()) {
case UsageEvents.Event.ACTIVITY_RESUMED:
case UsageEvents.Event.ACTIVITY_PAUSED:
@@ -2604,8 +2659,6 @@
}
}
}
-
- mIsProcessing = false;
}
}
@@ -3883,11 +3936,6 @@
return mQcConstants;
}
- @VisibleForTesting
- boolean isActiveBackgroundProcessing() {
- return mHandler.mIsProcessing;
- }
-
//////////////////////////// DATA DUMP //////////////////////////////
@Override
diff --git a/apex/jobscheduler/service/jni/Android.bp b/apex/jobscheduler/service/jni/Android.bp
index 4bcc165..c630217 100644
--- a/apex/jobscheduler/service/jni/Android.bp
+++ b/apex/jobscheduler/service/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_library_shared {
name: "libalarm_jni",
diff --git a/apex/media/service/Android.bp b/apex/media/service/Android.bp
index 5b24cfa..9b3399e 100644
--- a/apex/media/service/Android.bp
+++ b/apex/media/service/Android.bp
@@ -11,6 +11,15 @@
// WITHOUT 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "service-media-s-sources",
srcs: [
@@ -38,4 +47,3 @@
"com.android.media",
],
}
-
diff --git a/cmds/abx/Android.bp b/cmds/abx/Android.bp
index 333aced..50a0b75 100644
--- a/cmds/abx/Android.bp
+++ b/cmds/abx/Android.bp
@@ -1,4 +1,21 @@
+package {
+ default_applicable_licenses: ["frameworks_base_cmds_abx_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_base_cmds_abx_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
java_binary {
name: "abx",
wrapper: "abx",
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 4b7eda0..ed717c4 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.annotation.UserIdInt;
import android.app.backup.BackupManager;
-import android.app.backup.BackupManager.OperationType;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupProgress;
import android.app.backup.BackupTransport;
@@ -667,7 +666,7 @@
// The rest of the 'list' options work with a restore session on the current transport
try {
- mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null, OperationType.BACKUP);
+ mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
if (mRestore == null) {
System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
return;
@@ -822,7 +821,7 @@
try {
boolean didRestore = false;
- mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null, OperationType.BACKUP);
+ mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
if (mRestore == null) {
System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
return;
diff --git a/cmds/hid/OWNERS b/cmds/hid/OWNERS
new file mode 100644
index 0000000..d701f23
--- /dev/null
+++ b/cmds/hid/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/hardware/input/OWNERS
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index 422c2be..2cda57d 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -48,6 +48,7 @@
static struct {
jmethodID onDeviceOpen;
jmethodID onDeviceGetReport;
+ jmethodID onDeviceSetReport;
jmethodID onDeviceOutput;
jmethodID onDeviceError;
} gDeviceCallbackClassInfo;
@@ -113,10 +114,18 @@
checkAndClearException(env, "onDeviceGetReport");
}
-void DeviceCallback::onDeviceOutput(uint8_t eventId, uint8_t rType,
+void DeviceCallback::onDeviceSetReport(uint8_t rType,
const std::vector<uint8_t>& data) {
JNIEnv* env = getJNIEnv();
- env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceOutput, eventId, rType,
+ env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceSetReport, rType,
+ toJbyteArray(env, data).get());
+ checkAndClearException(env, "onDeviceSetReport");
+}
+
+void DeviceCallback::onDeviceOutput(uint8_t rType,
+ const std::vector<uint8_t>& data) {
+ JNIEnv* env = getJNIEnv();
+ env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceOutput, rType,
toJbyteArray(env, data).get());
checkAndClearException(env, "onDeviceOutput");
}
@@ -262,7 +271,7 @@
ALOGD("Received SET_REPORT: id=%" PRIu32 " rnum=%" PRIu8 " data=%s", set_report.id,
set_report.rnum, toString(data).c_str());
}
- mDeviceCallback->onDeviceOutput(UHID_SET_REPORT, set_report.rtype, data);
+ mDeviceCallback->onDeviceSetReport(set_report.rtype, data);
break;
}
case UHID_OUTPUT: {
@@ -271,7 +280,7 @@
if (DEBUG_OUTPUT) {
ALOGD("UHID_OUTPUT rtype=%" PRIu8 " data=%s", output.rtype, toString(data).c_str());
}
- mDeviceCallback->onDeviceOutput(UHID_OUTPUT, output.rtype, data);
+ mDeviceCallback->onDeviceOutput(output.rtype, data);
break;
}
default: {
@@ -366,8 +375,10 @@
env->GetMethodID(clazz, "onDeviceOpen", "()V");
uhid::gDeviceCallbackClassInfo.onDeviceGetReport =
env->GetMethodID(clazz, "onDeviceGetReport", "(II)V");
+ uhid::gDeviceCallbackClassInfo.onDeviceSetReport =
+ env->GetMethodID(clazz, "onDeviceSetReport", "(B[B)V");
uhid::gDeviceCallbackClassInfo.onDeviceOutput =
- env->GetMethodID(clazz, "onDeviceOutput", "(BB[B)V");
+ env->GetMethodID(clazz, "onDeviceOutput", "(B[B)V");
uhid::gDeviceCallbackClassInfo.onDeviceError =
env->GetMethodID(clazz, "onDeviceError", "()V");
if (uhid::gDeviceCallbackClassInfo.onDeviceOpen == NULL ||
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
index bb73132..d10a9aa 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.h
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -31,7 +31,8 @@
void onDeviceOpen();
void onDeviceGetReport(uint32_t requestId, uint8_t reportId);
- void onDeviceOutput(uint8_t eventId, uint8_t rType, const std::vector<uint8_t>& data);
+ void onDeviceSetReport(uint8_t rType, const std::vector<uint8_t>& data);
+ void onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data);
void onDeviceError();
private:
diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java
index 37d0b1c..95b1e9a 100644
--- a/cmds/hid/src/com/android/commands/hid/Device.java
+++ b/cmds/hid/src/com/android/commands/hid/Device.java
@@ -199,8 +199,8 @@
mHandler.sendMessageAtTime(msg, mTimeToSend);
}
- // native callback
- public void onDeviceOutput(byte eventId, byte rtype, byte[] data) {
+ // Send out the report to HID command output
+ private void sendReportOutput(byte eventId, byte rtype, byte[] data) {
JSONObject json = new JSONObject();
try {
json.put("eventId", eventId);
@@ -221,6 +221,18 @@
throw new RuntimeException(e);
}
+ }
+
+ // native callback
+ public void onDeviceSetReport(byte rtype, byte[] data) {
+ // We don't need to reply for the SET_REPORT but just send it to HID output for test
+ // verification.
+ sendReportOutput(UHID_EVENT_TYPE_SET_REPORT, rtype, data);
+ }
+
+ // native callback
+ public void onDeviceOutput(byte rtype, byte[] data) {
+ sendReportOutput(UHID_EVENT_TYPE_UHID_OUTPUT, rtype, data);
if (mOutputs == null) {
Log.e(TAG, "Received OUTPUT request, but 'outputs' section is not found");
return;
diff --git a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
index a0361d0..ca9df39 100644
--- a/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
+++ b/cmds/requestsync/src/com/android/commands/requestsync/RequestSync.java
@@ -182,6 +182,8 @@
mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
} else if (opt.equals("--rc") || opt.equals("--require-charging")) {
mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING, true);
+ } else if (opt.equals("--ej") || opt.equals("--schedule-as-ej")) {
+ mExtras.putBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, true);
} else if (opt.equals("-e") || opt.equals("--es") || opt.equals("--extra-string")) {
final String key = nextArgRequired();
final String value = nextArgRequired();
diff --git a/cmds/uinput/Android.bp b/cmds/uinput/Android.bp
index 0d7fed2..260cfc7 100644
--- a/cmds/uinput/Android.bp
+++ b/cmds/uinput/Android.bp
@@ -1,6 +1,23 @@
// Copyright 2020 The Android Open Source Project
//
+package {
+ default_applicable_licenses: ["frameworks_base_cmds_uinput_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_base_cmds_uinput_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
java_binary {
name: "uinput",
wrapper: "uinput",
@@ -15,4 +32,4 @@
srcs: [
"src/com/android/commands/uinput/InputAbsInfo.aidl",
],
-}
\ No newline at end of file
+}
diff --git a/cmds/uinput/jni/Android.bp b/cmds/uinput/jni/Android.bp
index 199bbbd..c56adc3 100644
--- a/cmds/uinput/jni/Android.bp
+++ b/cmds/uinput/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_cmds_uinput_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_cmds_uinput_license"],
+}
+
cc_library_shared {
name: "libuinputcommand_jni",
diff --git a/core/api/current.txt b/core/api/current.txt
index a5eb2ff..8d8ab57 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -507,6 +507,7 @@
field public static final int dashGap = 16843175; // 0x10101a7
field public static final int dashWidth = 16843174; // 0x10101a6
field public static final int data = 16842798; // 0x101002e
+ field public static final int dataExtractionRules = 16844350; // 0x101063e
field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
field public static final int datePickerMode = 16843955; // 0x10104b3
field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -5610,6 +5611,7 @@
field public static final int DEFAULT_LIGHTS = 4; // 0x4
field public static final int DEFAULT_SOUND = 1; // 0x1
field public static final int DEFAULT_VIBRATE = 2; // 0x2
+ field public static final String EXTRA_ANSWER_COLOR = "android.answerColor";
field public static final String EXTRA_ANSWER_INTENT = "android.answerIntent";
field public static final String EXTRA_AUDIO_CONTENTS_URI = "android.audioContents";
field public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
@@ -5621,6 +5623,7 @@
field public static final String EXTRA_COLORIZED = "android.colorized";
field public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
field public static final String EXTRA_CONVERSATION_TITLE = "android.conversationTitle";
+ field public static final String EXTRA_DECLINE_COLOR = "android.declineColor";
field public static final String EXTRA_DECLINE_INTENT = "android.declineIntent";
field public static final String EXTRA_HANG_UP_INTENT = "android.hangUpIntent";
field public static final String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
@@ -5908,6 +5911,8 @@
method @NonNull public static android.app.Notification.CallStyle forIncomingCall(@NonNull android.app.Person, @NonNull android.app.PendingIntent, @NonNull android.app.PendingIntent);
method @NonNull public static android.app.Notification.CallStyle forOngoingCall(@NonNull android.app.Person, @NonNull android.app.PendingIntent);
method @NonNull public static android.app.Notification.CallStyle forScreeningCall(@NonNull android.app.Person, @NonNull android.app.PendingIntent, @NonNull android.app.PendingIntent);
+ method @NonNull public android.app.Notification.CallStyle setAnswerButtonColorHint(@ColorInt int);
+ method @NonNull public android.app.Notification.CallStyle setDeclineButtonColorHint(@ColorInt int);
method @NonNull public android.app.Notification.CallStyle setVerificationIcon(@Nullable android.graphics.drawable.Icon);
method @NonNull public android.app.Notification.CallStyle setVerificationText(@Nullable CharSequence);
}
@@ -8371,7 +8376,9 @@
method protected android.view.View getDefaultView();
method protected android.view.View getErrorView();
method protected void prepareView(android.view.View);
+ method public void resetColorResources();
method public void setAppWidget(int, android.appwidget.AppWidgetProviderInfo);
+ method public void setColorResources(@NonNull android.util.SparseIntArray);
method public void setCurrentSize(@NonNull android.graphics.PointF);
method public void setExecutor(java.util.concurrent.Executor);
method public void setOnLightBackground(boolean);
@@ -8452,7 +8459,7 @@
method public int describeContents();
method public final android.os.UserHandle getProfile();
method @NonNull public android.content.pm.ActivityInfo getProviderInfo();
- method @Nullable public final String loadDescription(@NonNull android.content.Context);
+ method @Nullable public final CharSequence loadDescription(@NonNull android.content.Context);
method public final android.graphics.drawable.Drawable loadIcon(@NonNull android.content.Context, int);
method public final String loadLabel(android.content.pm.PackageManager);
method public final android.graphics.drawable.Drawable loadPreviewImage(@NonNull android.content.Context, int);
@@ -8470,7 +8477,7 @@
field public static final int WIDGET_FEATURE_RECONFIGURABLE = 1; // 0x1
field public int autoAdvanceViewId;
field public android.content.ComponentName configure;
- field @IdRes public int descriptionResource;
+ field @IdRes public int descriptionRes;
field public int icon;
field public int initialKeyguardLayout;
field public int initialLayout;
@@ -9734,7 +9741,7 @@
public interface DeviceFilter<D extends android.os.Parcelable> extends android.os.Parcelable {
}
- public class DeviceNotAssociatedException extends java.lang.Exception {
+ public class DeviceNotAssociatedException extends java.lang.RuntimeException {
}
public final class WifiDeviceFilter implements android.companion.DeviceFilter<android.net.wifi.ScanResult> {
@@ -10238,6 +10245,7 @@
field public static final String SYNC_EXTRAS_MANUAL = "force";
field public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
field public static final String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
+ field public static final String SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB = "schedule_as_expedited_job";
field public static final String SYNC_EXTRAS_UPLOAD = "upload";
field public static final int SYNC_OBSERVER_TYPE_ACTIVE = 4; // 0x4
field public static final int SYNC_OBSERVER_TYPE_PENDING = 2; // 0x2
@@ -10381,7 +10389,7 @@
method public abstract void grantUriPermission(String, android.net.Uri, int);
method public abstract boolean isDeviceProtectedStorage();
method public boolean isRestricted();
- method public static boolean isUiContext(@NonNull android.content.Context);
+ method public boolean isUiContext();
method public abstract boolean moveDatabaseFrom(android.content.Context, String);
method public abstract boolean moveSharedPreferencesFrom(android.content.Context, String);
method @NonNull public final android.content.res.TypedArray obtainStyledAttributes(@NonNull @StyleableRes int[]);
@@ -11560,6 +11568,7 @@
method public android.content.SyncRequest.Builder setManual(boolean);
method public android.content.SyncRequest.Builder setNoRetry(boolean);
method public android.content.SyncRequest.Builder setRequiresCharging(boolean);
+ method @NonNull public android.content.SyncRequest.Builder setScheduleAsExpeditedJob(boolean);
method public android.content.SyncRequest.Builder setSyncAdapter(android.accounts.Account, String);
method public android.content.SyncRequest.Builder syncOnce();
method public android.content.SyncRequest.Builder syncPeriodic(long, long);
@@ -18559,23 +18568,6 @@
package android.hardware.display {
- public final class DeviceProductInfo implements android.os.Parcelable {
- method public int describeContents();
- method public int getConnectionToSinkType();
- method public int getManufactureWeek();
- method public int getManufactureYear();
- method @NonNull public String getManufacturerPnpId();
- method public int getModelYear();
- method @Nullable public String getName();
- method @NonNull public String getProductId();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int CONNECTION_TO_SINK_BUILT_IN = 1; // 0x1
- field public static final int CONNECTION_TO_SINK_DIRECT = 2; // 0x2
- field public static final int CONNECTION_TO_SINK_TRANSITIVE = 3; // 0x3
- field public static final int CONNECTION_TO_SINK_UNKNOWN = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.DeviceProductInfo> CREATOR;
- }
-
public final class DisplayManager {
method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, @Nullable android.view.Surface, int);
method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler);
@@ -18904,6 +18896,7 @@
public abstract class AbstractInputMethodService extends android.app.Service implements android.view.KeyEvent.Callback {
ctor public AbstractInputMethodService();
method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
+ method public final boolean isUiContext();
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl onCreateInputMethodInterface();
method public abstract android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
@@ -19669,6 +19662,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void addProximityAlert(double, double, float, long, @NonNull android.app.PendingIntent);
method public void addTestProvider(@NonNull String, boolean, boolean, boolean, boolean, boolean, boolean, boolean, int, int);
method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties);
+ method public void addTestProvider(@NonNull String, @NonNull android.location.provider.ProviderProperties, @NonNull java.util.Set<java.lang.String>);
method @Deprecated public void clearTestProviderEnabled(@NonNull String);
method @Deprecated public void clearTestProviderLocation(@NonNull String);
method @Deprecated public void clearTestProviderStatus(@NonNull String);
@@ -26296,6 +26290,7 @@
field public static final int NET_CAPABILITY_CBS = 5; // 0x5
field public static final int NET_CAPABILITY_DUN = 2; // 0x2
field public static final int NET_CAPABILITY_EIMS = 10; // 0xa
+ field public static final int NET_CAPABILITY_ENTERPRISE = 29; // 0x1d
field public static final int NET_CAPABILITY_FOREGROUND = 19; // 0x13
field public static final int NET_CAPABILITY_FOTA = 3; // 0x3
field public static final int NET_CAPABILITY_IA = 7; // 0x7
@@ -30663,8 +30658,8 @@
}
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);
+ method @WorkerThread public void cancelBugreport();
+ method @WorkerThread public void startConnectivityBugreport(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
}
public abstract static class BugreportManager.BugreportCallback {
@@ -35126,6 +35121,7 @@
field public static final String ACTION_QUICK_ACCESS_WALLET_SETTINGS = "android.settings.QUICK_ACCESS_WALLET_SETTINGS";
field public static final String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
field public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS";
+ field public static final String ACTION_REQUEST_SCHEDULE_EXACT_ALARM = "android.settings.REQUEST_SCHEDULE_EXACT_ALARM";
field public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE = "android.settings.REQUEST_SET_AUTOFILL_SERVICE";
field public static final String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS";
field public static final String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS";
@@ -37170,8 +37166,10 @@
method @NonNull public static android.content.Intent createInstallIntent();
method @NonNull public static android.content.Intent createManageCredentialsIntent(@NonNull android.security.AppUriAuthenticationPolicy);
method @Nullable @WorkerThread public static java.security.cert.X509Certificate[] getCertificateChain(@NonNull android.content.Context, @NonNull String) throws java.lang.InterruptedException, android.security.KeyChainException;
+ method @NonNull public static android.security.AppUriAuthenticationPolicy getCredentialManagementAppPolicy(@NonNull android.content.Context) throws java.lang.SecurityException;
method @Nullable @WorkerThread public static java.security.PrivateKey getPrivateKey(@NonNull android.content.Context, @NonNull String) throws java.lang.InterruptedException, android.security.KeyChainException;
method @Deprecated public static boolean isBoundKeyAlgorithm(@NonNull String);
+ method public static boolean isCredentialManagementApp(@NonNull android.content.Context);
method public static boolean isKeyAlgorithmSupported(@NonNull String);
field public static final String ACTION_KEYCHAIN_CHANGED = "android.security.action.KEYCHAIN_CHANGED";
field public static final String ACTION_KEY_ACCESS_CHANGED = "android.security.action.KEY_ACCESS_CHANGED";
@@ -41242,6 +41240,7 @@
field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e
field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f
field public static final int ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED = 65; // 0x41
+ field public static final int ALL_MATCHING_RULES_FAILED = 2254; // 0x8ce
field public static final int APN_DISABLED = 2045; // 0x7fd
field public static final int APN_DISALLOWED_ON_ROAMING = 2059; // 0x80b
field public static final int APN_MISMATCH = 2054; // 0x806
@@ -41391,6 +41390,7 @@
field public static final int LTE_NAS_SERVICE_REQUEST_FAILED = 2117; // 0x845
field public static final int LTE_THROTTLING_NOT_REQUIRED = 2127; // 0x84f
field public static final int MAC_FAILURE = 2183; // 0x887
+ field public static final int MATCH_ALL_RULE_NOT_ALLOWED = 2253; // 0x8cd
field public static final int MAXIMIUM_NSAPIS_EXCEEDED = 2157; // 0x86d
field public static final int MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 2166; // 0x876
field public static final int MAX_ACCESS_PROBE = 2079; // 0x81f
@@ -42176,6 +42176,7 @@
method @NonNull public android.telephony.SmsManager createForSubscriptionId(int);
method public java.util.ArrayList<java.lang.String> divideMessage(String);
method public void downloadMultimediaMessage(android.content.Context, String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
+ method public void downloadMultimediaMessage(@NonNull android.content.Context, @NonNull String, @NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent, long);
method @NonNull public android.os.Bundle getCarrierConfigValues();
method @Deprecated public static android.telephony.SmsManager getDefault();
method public static int getDefaultSmsSubscriptionId();
@@ -42187,6 +42188,7 @@
method public void injectSmsPdu(byte[], String, android.app.PendingIntent);
method public void sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
method public void sendMultimediaMessage(android.content.Context, android.net.Uri, String, android.os.Bundle, android.app.PendingIntent);
+ method public void sendMultimediaMessage(@NonNull android.content.Context, @NonNull android.net.Uri, @Nullable String, @Nullable android.os.Bundle, @Nullable android.app.PendingIntent, long);
method public void sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
method public void sendMultipartTextMessage(@NonNull String, @Nullable String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, long);
method public void sendMultipartTextMessage(@NonNull String, @Nullable String, @NonNull java.util.List<java.lang.String>, @Nullable java.util.List<android.app.PendingIntent>, @Nullable java.util.List<android.app.PendingIntent>, @NonNull String, @Nullable String);
@@ -46704,7 +46706,6 @@
method public long getAppVsyncOffsetNanos();
method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
method @Nullable public android.view.DisplayCutout getCutout();
- method @Nullable public android.hardware.display.DeviceProductInfo getDeviceProductInfo();
method public int getDisplayId();
method public int getFlags();
method public android.view.Display.HdrCapabilities getHdrCapabilities();
@@ -48034,10 +48035,15 @@
}
public class SoundEffectConstants {
+ method public static int getConstantForFocusDirection(int, boolean);
method public static int getContantForFocusDirection(int);
field public static final int CLICK = 0; // 0x0
field public static final int NAVIGATION_DOWN = 4; // 0x4
field public static final int NAVIGATION_LEFT = 1; // 0x1
+ field public static final int NAVIGATION_REPEAT_DOWN = 8; // 0x8
+ field public static final int NAVIGATION_REPEAT_LEFT = 5; // 0x5
+ field public static final int NAVIGATION_REPEAT_RIGHT = 7; // 0x7
+ field public static final int NAVIGATION_REPEAT_UP = 6; // 0x6
field public static final int NAVIGATION_RIGHT = 3; // 0x3
field public static final int NAVIGATION_UP = 2; // 0x2
}
@@ -53391,6 +53397,7 @@
method public int getCheckedItemPosition();
method public android.util.SparseBooleanArray getCheckedItemPositions();
method public int getChoiceMode();
+ method public int getEdgeEffectType();
method public int getListPaddingBottom();
method public int getListPaddingLeft();
method public int getListPaddingRight();
@@ -53432,6 +53439,7 @@
method public void setChoiceMode(int);
method public void setDrawSelectorOnTop(boolean);
method public void setEdgeEffectColor(@ColorInt int);
+ method public void setEdgeEffectType(int);
method public void setFastScrollAlwaysVisible(boolean);
method public void setFastScrollEnabled(boolean);
method public void setFastScrollStyle(int);
@@ -54440,6 +54448,7 @@
method public boolean executeKeyEvent(android.view.KeyEvent);
method public void fling(int);
method public boolean fullScroll(int);
+ method public int getEdgeEffectType();
method @ColorInt public int getLeftEdgeEffectColor();
method public int getMaxScrollAmount();
method @ColorInt public int getRightEdgeEffectColor();
@@ -54447,6 +54456,7 @@
method public boolean isSmoothScrollingEnabled();
method public boolean pageScroll(int);
method public void setEdgeEffectColor(@ColorInt int);
+ method public void setEdgeEffectType(int);
method public void setFillViewport(boolean);
method public void setLeftEdgeEffectColor(@ColorInt int);
method public void setRightEdgeEffectColor(@ColorInt int);
@@ -55300,6 +55310,7 @@
method public void fling(int);
method public boolean fullScroll(int);
method @ColorInt public int getBottomEdgeEffectColor();
+ method public int getEdgeEffectType();
method public int getMaxScrollAmount();
method @ColorInt public int getTopEdgeEffectColor();
method public boolean isFillViewport();
@@ -55308,6 +55319,7 @@
method public void scrollToDescendant(@NonNull android.view.View);
method public void setBottomEdgeEffectColor(@ColorInt int);
method public void setEdgeEffectColor(@ColorInt int);
+ method public void setEdgeEffectType(int);
method public void setFillViewport(boolean);
method public void setSmoothScrollingEnabled(boolean);
method public void setTopEdgeEffectColor(@ColorInt int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0d304b6..5734cbd 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -176,6 +176,7 @@
field public static final String OBSERVE_APP_USAGE = "android.permission.OBSERVE_APP_USAGE";
field public static final String OBSERVE_NETWORK_POLICY = "android.permission.OBSERVE_NETWORK_POLICY";
field public static final String OBSERVE_ROLE_HOLDERS = "android.permission.OBSERVE_ROLE_HOLDERS";
+ field public static final String OBSERVE_SENSOR_PRIVACY = "android.permission.OBSERVE_SENSOR_PRIVACY";
field public static final String OPEN_ACCESSIBILITY_DETAILS_SETTINGS = "android.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS";
field public static final String OVERRIDE_WIFI_CONFIG = "android.permission.OVERRIDE_WIFI_CONFIG";
field public static final String PACKAGE_VERIFICATION_AGENT = "android.permission.PACKAGE_VERIFICATION_AGENT";
@@ -884,7 +885,7 @@
public class DevicePolicyManager {
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner();
- method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"}) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwnerNameOnAnyUser();
method @Nullable public CharSequence getDeviceOwnerOrganizationName();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser();
@@ -1826,7 +1827,7 @@
method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public android.bluetooth.BufferConstraints getBufferConstraints();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getDynamicBufferSupport();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setBufferMillis(int, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setBufferLengthMillis(int, int);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD = 1; // 0x1
field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING = 2; // 0x2
@@ -2032,7 +2033,7 @@
public final class BufferConstraints implements android.os.Parcelable {
ctor public BufferConstraints(@NonNull java.util.List<android.bluetooth.BufferConstraint>);
method public int describeContents();
- method @Nullable public android.bluetooth.BufferConstraint getCodec(int);
+ method @Nullable public android.bluetooth.BufferConstraint forCodec(int);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final int BUFFER_CODEC_MAX_NUM = 32; // 0x20
field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraints> CREATOR;
@@ -2550,10 +2551,12 @@
field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
+ field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
field public static final String FEATURE_CONTEXT_HUB = "android.hardware.context_hub";
field public static final String FEATURE_CROSS_LAYER_BLUR = "android.software.cross_layer_blur";
field @Deprecated public static final String FEATURE_INCREMENTAL_DELIVERY = "android.software.incremental_delivery";
field public static final String FEATURE_INCREMENTAL_DELIVERY_VERSION = "android.software.incremental_delivery_version";
+ field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
field public static final String FEATURE_REBOOT_ESCROW = "android.hardware.reboot_escrow";
field public static final String FEATURE_TELEPHONY_CARRIERLOCK = "android.hardware.telephony.carrierlock";
field public static final String FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION = "android.hardware.telephony.ims.singlereg";
@@ -2908,6 +2911,22 @@
method public boolean injectSensorData(android.hardware.Sensor, float[], int, long);
}
+ public final class SensorPrivacyManager {
+ method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+ method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+ method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int);
+ method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+ }
+
+ public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener {
+ method public void onSensorPrivacyChanged(boolean);
+ }
+
+ public static class SensorPrivacyManager.Sensors {
+ field public static final int CAMERA = 2; // 0x2
+ field public static final int MICROPHONE = 1; // 0x1
+ }
+
}
package android.hardware.biometrics {
@@ -4688,6 +4707,7 @@
}
public class LocationManager {
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void addProviderRequestChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.ChangedListener);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void flushGnssBatch();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
method @Nullable public String getExtraLocationControllerPackage();
@@ -4702,7 +4722,7 @@
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String, @Nullable String);
method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean registerProviderRequestListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.provider.ProviderRequest.Listener);
+ method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void removeProviderRequestChangedListener(@NonNull android.location.provider.ProviderRequest.ChangedListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
@@ -4711,7 +4731,6 @@
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void unregisterProviderRequestListener(@NonNull android.location.provider.ProviderRequest.Listener);
}
public final class LocationRequest implements android.os.Parcelable {
@@ -4861,7 +4880,7 @@
method @NonNull public android.location.provider.ProviderRequest.Builder setWorkSource(@NonNull android.os.WorkSource);
}
- public static interface ProviderRequest.Listener {
+ public static interface ProviderRequest.ChangedListener {
method public void onProviderRequestChanged(@NonNull String, @NonNull android.location.provider.ProviderRequest);
}
@@ -5072,7 +5091,7 @@
}
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
- method @RequiresPermission(android.Manifest.permission.BIND_IMS_SERVICE) public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler);
+ method @RequiresPermission(android.Manifest.permission.BIND_IMS_SERVICE) public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener);
}
public static interface MediaPlayer.OnRtpRxNoticeListener {
@@ -7916,6 +7935,28 @@
}
+package android.net.vcn {
+
+ public class VcnManager {
+ method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void addVcnNetworkPolicyListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public android.net.vcn.VcnNetworkPolicyResult applyVcnNetworkPolicy(@NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties);
+ method public void removeVcnNetworkPolicyListener(@NonNull android.net.vcn.VcnManager.VcnNetworkPolicyListener);
+ }
+
+ public static interface VcnManager.VcnNetworkPolicyListener {
+ method public void onPolicyChanged();
+ }
+
+ public final class VcnNetworkPolicyResult implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+ method public boolean isTeardownRequested();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.vcn.VcnNetworkPolicyResult> CREATOR;
+ }
+
+}
+
package android.net.wifi {
public final class WifiMigration {
@@ -8263,7 +8304,7 @@
public final class BugreportManager {
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);
+ method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread 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 final class BugreportParams {
@@ -10741,7 +10782,7 @@
method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
method @Nullable public final String getTelecomCallId();
method @Deprecated public void onAudioStateChanged(android.telecom.AudioState);
- method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, boolean);
+ method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(@NonNull android.telecom.Connection.CallFilteringCompletionInfo);
method public final void resetConnectionTime();
method public void setCallDirection(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectTimeMillis(@IntRange(from=0) long);
@@ -10757,6 +10798,16 @@
field public static final int PROPERTY_REMOTELY_HOSTED = 2048; // 0x800
}
+ public static final class Connection.CallFilteringCompletionInfo implements android.os.Parcelable {
+ ctor public Connection.CallFilteringCompletionInfo(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, @Nullable android.content.ComponentName);
+ method public int describeContents();
+ method @Nullable public android.telecom.CallScreeningService.CallResponse getCallResponse();
+ method @Nullable public android.content.ComponentName getCallScreeningComponent();
+ method public boolean isBlocked();
+ method public boolean isInContacts();
+ field @NonNull public static final android.os.Parcelable.Creator<android.telecom.Connection.CallFilteringCompletionInfo> CREATOR;
+ }
+
public final class ConnectionRequest implements android.os.Parcelable {
method @Nullable public String getTelecomCallId();
}
@@ -10918,7 +10969,7 @@
}
public final class RemoteConnection {
- method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(boolean, boolean, @Nullable android.telecom.CallScreeningService.CallResponse, boolean);
+ method @RequiresPermission(android.Manifest.permission.READ_CONTACTS) public void onCallFilteringCompleted(@NonNull android.telecom.Connection.CallFilteringCompletionInfo);
method @Deprecated public void setAudioState(android.telecom.AudioState);
}
@@ -12229,6 +12280,7 @@
method public long getRetryDurationMillis();
method @Nullable public android.telephony.data.SliceInfo getSliceInfo();
method @Deprecated public int getSuggestedRetryTime();
+ method @NonNull public java.util.List<android.telephony.data.TrafficDescriptor> getTrafficDescriptors();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR;
field public static final int HANDOVER_FAILURE_MODE_DO_FALLBACK = 1; // 0x1
@@ -12264,6 +12316,7 @@
method @NonNull public android.telephony.data.DataCallResponse.Builder setRetryDurationMillis(long);
method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.SliceInfo);
method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setTrafficDescriptors(@NonNull java.util.List<android.telephony.data.TrafficDescriptor>);
}
public final class DataProfile implements android.os.Parcelable {
@@ -12334,7 +12387,7 @@
method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
- method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @NonNull android.telephony.data.DataServiceCallback);
+ method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @Nullable android.telephony.data.TrafficDescriptor, boolean, @NonNull android.telephony.data.DataServiceCallback);
}
public class DataServiceCallback {
@@ -12433,6 +12486,15 @@
method @NonNull public android.telephony.data.ThrottleStatus.Builder setTransportType(int);
}
+ public final class TrafficDescriptor implements android.os.Parcelable {
+ ctor public TrafficDescriptor(@Nullable String, @Nullable String);
+ method public int describeContents();
+ method @Nullable public String getDnn();
+ method @Nullable public String getOsAppId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.TrafficDescriptor> CREATOR;
+ }
+
}
package android.telephony.euicc {
@@ -14252,21 +14314,10 @@
public final class UwbManager {
method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public long elapsedRealtimeResolutionNanos();
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getAngleOfArrivalSupport();
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxRemoteDevicesPerInitiatorSession();
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxRemoteDevicesPerResponderSession();
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public int getMaxSimultaneousSessions();
method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public android.os.PersistableBundle getSpecificationInfo();
- method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public java.util.List<java.lang.Integer> getSupportedChannelNumbers();
- method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public java.util.Set<java.lang.Integer> getSupportedPreambleCodeIndices();
- method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public boolean isRangingSupported();
method @NonNull @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public AutoCloseable openRangingSession(@NonNull android.os.PersistableBundle, @NonNull java.util.concurrent.Executor, @NonNull android.uwb.RangingSession.Callback);
method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void registerAdapterStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.uwb.UwbManager.AdapterStateCallback);
method @RequiresPermission(android.Manifest.permission.UWB_PRIVILEGED) public void unregisterAdapterStateCallback(@NonNull android.uwb.UwbManager.AdapterStateCallback);
- field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D = 2; // 0x2
- field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 3; // 0x3
- field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 4; // 0x4
- field public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE = 1; // 0x1
}
public static interface UwbManager.AdapterStateCallback {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index a02320d..6231b95 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -10,9 +10,11 @@
field public static final String BROADCAST_CLOSE_SYSTEM_DIALOGS = "android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS";
field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
field public static final String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
+ field public static final String CLEAR_FREEZE_PERIOD = "android.permission.CLEAR_FREEZE_PERIOD";
field public static final String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
field public static final String CONTROL_DEVICE_LIGHTS = "android.permission.CONTROL_DEVICE_LIGHTS";
field public static final String CONTROL_DEVICE_STATE = "android.permission.CONTROL_DEVICE_STATE";
+ field public static final String FORCE_DEVICE_POLICY_MANAGER_LOGS = "android.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS";
field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
field public static final String KEEP_UNINSTALLED_PACKAGES = "android.permission.KEEP_UNINSTALLED_PACKAGES";
field @Deprecated public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
@@ -91,6 +93,8 @@
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
method public long getTotalRam();
+ method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidProcessCapabilities(int);
+ method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidProcessState(int);
method public void holdLock(android.os.IBinder, int);
method public static boolean isHighEndGfx();
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
@@ -106,7 +110,10 @@
field public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 2; // 0x2
field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1
field public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 4; // 0x4
+ field public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0
+ field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
+ field public static final int PROCESS_STATE_TOP = 2; // 0x2
}
public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
@@ -384,7 +391,11 @@
public class DevicePolicyManager {
method public int checkProvisioningPreCondition(@Nullable String, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.CLEAR_FREEZE_PERIOD) public void clearSystemUpdatePolicyFreezePeriodRecord();
method @Nullable public android.os.UserHandle createAndProvisionManagedProfile(@NonNull android.app.admin.ManagedProfileProvisioningParams) throws android.app.admin.ProvisioningException;
+ method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceNetworkLogs();
+ method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void forceRemoveActiveAdmin(@NonNull android.content.ComponentName, int);
+ method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceSecurityLogs();
method public void forceUpdateUserSetupComplete();
method public long getLastBugReportRequestTime();
method public long getLastNetworkLogRetrievalTime();
@@ -392,10 +403,13 @@
method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle);
method public boolean isCurrentInputMethodSetByOwner();
method public boolean isFactoryResetProtectionPolicySupported();
+ method @RequiresPermission(anyOf={"android.permission.MARK_DEVICE_ORGANIZATION_OWNED", "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"}, conditional=true) public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull android.content.ComponentName);
method @NonNull public static String operationSafetyReasonToString(int);
method @NonNull public static String operationToString(int);
method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void provisionFullyManagedDevice(@NonNull android.app.admin.FullyManagedDeviceProvisioningParams) throws android.app.admin.ProvisioningException;
method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void resetDefaultCrossProfileIntentFilters(int);
+ method @RequiresPermission(allOf={"android.permission.MANAGE_DEVICE_ADMINS", android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int);
+ method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public boolean setDeviceOwner(@NonNull android.content.ComponentName, @Nullable String, int);
method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, int);
field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
field public static final int CODE_ACCOUNTS_NOT_EMPTY = 6; // 0x6
@@ -580,6 +594,14 @@
}
+package android.appwidget {
+
+ public class AppWidgetManager {
+ method public void setBindAppWidgetPermission(@NonNull String, int, boolean);
+ }
+
+}
+
package android.bluetooth {
public final class BluetoothClass implements android.os.Parcelable {
@@ -696,8 +718,10 @@
method public void holdLock(android.os.IBinder, int);
method @RequiresPermission(android.Manifest.permission.KEEP_UNINSTALLED_PACKAGES) public void setKeepUninstalledPackages(@NonNull java.util.List<java.lang.String>);
field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
+ field public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
field public static final String FEATURE_FILE_BASED_ENCRYPTION = "android.software.file_based_encryption";
field public static final String FEATURE_HDMI_CEC = "android.hardware.hdmi.cec";
+ field public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
field public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED = 128; // 0x80
field public static final int MATCH_KNOWN_PACKAGES = 4202496; // 0x402000
field public static final String SYSTEM_SHARED_LIBRARY_SERVICES = "android.ext.services";
@@ -858,11 +882,21 @@
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
+ method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+ method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void addSensorPrivacyListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+ method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public boolean isSensorPrivacyEnabled(int);
+ method @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY) public void removeSensorPrivacyListener(@NonNull android.hardware.SensorPrivacyManager.OnSensorPrivacyChangedListener);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacy(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) public void setSensorPrivacyForProfileGroup(int, boolean);
+ }
+
+ public static interface SensorPrivacyManager.OnSensorPrivacyChangedListener {
+ method public void onSensorPrivacyChanged(boolean);
+ }
+
+ public static class SensorPrivacyManager.Sensors {
+ field public static final int CAMERA = 2; // 0x2
+ field public static final int MICROPHONE = 1; // 0x1
}
}
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl
index 341393c..eb7cac07 100644
--- a/core/java/android/app/ActivityManager.aidl
+++ b/core/java/android/app/ActivityManager.aidl
@@ -17,6 +17,7 @@
package android.app;
parcelable ActivityManager.MemoryInfo;
+parcelable ActivityManager.PendingIntentInfo;
parcelable ActivityManager.ProcessErrorStateInfo;
parcelable ActivityManager.RecentTaskInfo;
parcelable ActivityManager.TaskDescription;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 220c332..f905ec8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -511,6 +511,7 @@
/** @hide Process is hosting the current top activities. Note that this covers
* all activities that are visible to the user. */
@UnsupportedAppUsage
+ @TestApi
public static final int PROCESS_STATE_TOP = ProcessStateEnum.TOP;
/** @hide Process is bound to a TOP app. */
@@ -518,6 +519,7 @@
/** @hide Process is hosting a foreground service. */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @TestApi
public static final int PROCESS_STATE_FOREGROUND_SERVICE = ProcessStateEnum.FOREGROUND_SERVICE;
/** @hide Process is hosting a foreground service due to a system binding. */
@@ -617,6 +619,7 @@
public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;
/** @hide Process can access network despite any power saving resrictions */
+ @TestApi
public static final int PROCESS_CAPABILITY_NETWORK = 1 << 3;
/** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/
@@ -3432,6 +3435,36 @@
}
/**
+ * Returns the process state of this uid.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+ public int getUidProcessState(int uid) {
+ try {
+ return getService().getUidProcessState(uid, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the process capability of this uid.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+ public @ProcessCapability int getUidProcessCapabilities(int uid) {
+ try {
+ return getService().getUidProcessCapabilities(uid, mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Return the importance of a given package name, based on the processes that are
* currently running. The return value is one of the importance constants defined
* in {@link RunningAppProcessInfo}, giving you the highest importance of all the
@@ -4776,4 +4809,71 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * A subset of immutable pending intent information suitable for caching on the client side.
+ *
+ * @hide
+ */
+ public static final class PendingIntentInfo implements Parcelable {
+
+ private final String mCreatorPackage;
+ private final int mCreatorUid;
+ private final boolean mImmutable;
+ private final int mIntentSenderType;
+
+ public PendingIntentInfo(String creatorPackage, int creatorUid, boolean immutable,
+ int intentSenderType) {
+ mCreatorPackage = creatorPackage;
+ mCreatorUid = creatorUid;
+ mImmutable = immutable;
+ mIntentSenderType = intentSenderType;
+ }
+
+ public String getCreatorPackage() {
+ return mCreatorPackage;
+ }
+
+ public int getCreatorUid() {
+ return mCreatorUid;
+ }
+
+ public boolean isImmutable() {
+ return mImmutable;
+ }
+
+ public int getIntentSenderType() {
+ return mIntentSenderType;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeString(mCreatorPackage);
+ parcel.writeInt(mCreatorUid);
+ parcel.writeBoolean(mImmutable);
+ parcel.writeInt(mIntentSenderType);
+ }
+
+ public static final @NonNull Creator<PendingIntentInfo> CREATOR =
+ new Creator<PendingIntentInfo>() {
+ @Override
+ public PendingIntentInfo createFromParcel(Parcel in) {
+ return new PendingIntentInfo(
+ /* creatorPackage= */ in.readString(),
+ /* creatorUid= */ in.readInt(),
+ /* immutable= */ in.readBoolean(),
+ /* intentSenderType= */ in.readInt());
+ }
+
+ @Override
+ public PendingIntentInfo[] newArray(int size) {
+ return new PendingIntentInfo[size];
+ }
+ };
+ }
}
diff --git a/core/java/android/app/AnrController.java b/core/java/android/app/AnrController.java
index cfc9d27..a0d4b3a 100644
--- a/core/java/android/app/AnrController.java
+++ b/core/java/android/app/AnrController.java
@@ -23,7 +23,29 @@
public interface AnrController {
/**
* Returns the delay in milliseconds for an ANR dialog that is about to be shown for
- * {@code packageName}.
+ * {@code packageName} with {@code uid}.
+ *
+ * Implementations should only return a positive value if they actually expect the
+ * {@code packageName} to be delayed due to them.
+
+ * If there are multiple controllers registered, the controller with the max delay will
+ * be selected and will receive an {@link #onAnrDelayStarted} callback at the start of the
+ * delay and an {@link #onAnrDelayCompleted} at the end of the delay.
*/
long getAnrDelayMillis(String packageName, int uid);
+
+ /**
+ * Notifies the controller at the start of the ANR dialog delay for {@code packageName} with
+ * {@code uid}. The controller can decide to show a progress UI after this notification.
+ */
+ void onAnrDelayStarted(String packageName, int uid);
+
+ /**
+ * Notifies the controller at the end of the ANR dialog delay for {@code packageName} with
+ * {@code uid}.
+ *
+ * @return whether the ANR dialog should be shown or cancelled. {@code true} if the
+ * ANR dialog should be shown, {@code false} if it should be cancelled.
+ */
+ boolean onAnrDelayCompleted(String packageName, int uid);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 2f3b50b..160844a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1141,23 +1141,20 @@
*
* @hide
*/
- // TODO: Add as AppProtoEnums
- public static final int OP_PHONE_CALL_MICROPHONE = 100;
+ public static final int OP_PHONE_CALL_MICROPHONE = AppProtoEnums.APP_OP_PHONE_CALL_MICROPHONE;
/**
* Phone call is using camera
*
* @hide
*/
- // TODO: Add as AppProtoEnums
- public static final int OP_PHONE_CALL_CAMERA = 101;
+ public static final int OP_PHONE_CALL_CAMERA = AppProtoEnums.APP_OP_PHONE_CALL_CAMERA;
/**
* Audio is being recorded for hotword detection.
*
* @hide
*/
- // TODO: Add as AppProtoEnums
- public static final int OP_RECORD_AUDIO_HOTWORD = 102;
+ public static final int OP_RECORD_AUDIO_HOTWORD = AppProtoEnums.APP_OP_RECORD_AUDIO_HOTWORD;
/**
* Manage credentials in the system KeyChain.
@@ -1184,10 +1181,29 @@
*/
public static final int OP_SCHEDULE_EXACT_ALARM = AppProtoEnums.APP_OP_SCHEDULE_EXACT_ALARM;
+ /**
+ * Fine location being accessed by a location source, which is
+ * a component that already has location data since it is the one
+ * that produces location, which is it is a data source for
+ * location data.
+ *
+ * @hide
+ */
+ public static final int OP_FINE_LOCATION_SOURCE = AppProtoEnums.APP_OP_FINE_LOCATION_SOURCE;
+
+ /**
+ * Coarse location being accessed by a location source, which is
+ * a component that already has location data since it is the one
+ * that produces location, which is it is a data source for
+ * location data.
+ *
+ * @hide
+ */
+ public static final int OP_COARSE_LOCATION_SOURCE = AppProtoEnums.APP_OP_COARSE_LOCATION_SOURCE;
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 108;
+ public static final int _NUM_OP = 110;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1567,6 +1583,24 @@
*/
public static final String OPSTR_SCHEDULE_EXACT_ALARM = "android:schedule_exact_alarm";
+ /**
+ * Fine location being accessed by a location source, which is
+ * a component that already has location since it is the one that
+ * produces location.
+ *
+ * @hide
+ */
+ public static final String OPSTR_FINE_LOCATION_SOURCE = "android:fine_location_source";
+
+ /**
+ * Coarse location being accessed by a location source, which is
+ * a component that already has location since it is the one that
+ * produces location.
+ *
+ * @hide
+ */
+ public static final String OPSTR_COARSE_LOCATION_SOURCE = "android:coarse_location_source";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1767,6 +1801,8 @@
OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
OP_RECORD_AUDIO_OUTPUT, // RECORD_AUDIO_OUTPUT
OP_SCHEDULE_EXACT_ALARM, // SCHEDULE_EXACT_ALARM
+ OP_FINE_LOCATION, // OP_FINE_LOCATION_SOURCE
+ OP_COARSE_LOCATION, // OP_COARSE_LOCATION_SOURCE
};
/**
@@ -1881,6 +1917,8 @@
OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
OPSTR_RECORD_AUDIO_OUTPUT,
OPSTR_SCHEDULE_EXACT_ALARM,
+ OPSTR_FINE_LOCATION_SOURCE,
+ OPSTR_COARSE_LOCATION_SOURCE,
};
/**
@@ -1996,6 +2034,8 @@
"USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER",
"RECORD_AUDIO_OUTPUT",
"SCHEDULE_EXACT_ALARM",
+ "FINE_LOCATION_SOURCE",
+ "COARSE_LOCATION_SOURCE",
};
/**
@@ -2112,6 +2152,8 @@
Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
null, // no permission for OP_RECORD_AUDIO_OUTPUT
Manifest.permission.SCHEDULE_EXACT_ALARM,
+ null, // no permission for OP_ACCESS_FINE_LOCATION_SOURCE,
+ null, // no permission for OP_ACCESS_COARSE_LOCATION_SOURCE,
};
/**
@@ -2228,6 +2270,8 @@
null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
null, // RECORD_AUDIO_OUTPUT
null, // SCHEDULE_EXACT_ALARM
+ null, // ACCESS_FINE_LOCATION_SOURCE
+ null, // ACCESS_COARSE_LOCATION_SOURCE
};
/**
@@ -2343,6 +2387,8 @@
null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
null, // RECORD_AUDIO_OUTPUT
null, // SCHEDULE_EXACT_ALARM
+ null, // ACCESS_FINE_LOCATION_SOURCE
+ null, // ACCESS_COARSE_LOCATION_SOURCE
};
/**
@@ -2457,6 +2503,8 @@
AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_OUTPUT
AppOpsManager.MODE_DEFAULT, // SCHEDULE_EXACT_ALARM
+ AppOpsManager.MODE_ALLOWED, // ACCESS_FINE_LOCATION_SOURCE
+ AppOpsManager.MODE_ALLOWED, // ACCESS_COARSE_LOCATION_SOURCE
};
/**
@@ -2575,6 +2623,8 @@
true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
false, // RECORD_AUDIO_OUTPUT
false, // SCHEDULE_EXACT_ALARM
+ false, // ACCESS_FINE_LOCATION_SOURCE
+ false, // ACCESS_COARSE_LOCATION_SOURCE
};
/**
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 4ad13e1..2e684b1 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -17,6 +17,7 @@
package android.app;
import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
import android.app.ActivityTaskManager;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
@@ -248,7 +249,7 @@
in IBinder token, in String resultWho, int requestCode, in Intent[] intents,
in String[] resolvedTypes, int flags, in Bundle options, int userId);
void cancelIntentSender(in IIntentSender sender);
- String getPackageForIntentSender(in IIntentSender sender);
+ ActivityManager.PendingIntentInfo getInfoForIntentSender(in IIntentSender sender);
void registerIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
void unregisterIntentSenderCancelListener(in IIntentSender sender, in IResultReceiver receiver);
void enterSafeMode();
@@ -293,7 +294,6 @@
int operationType);
void backupAgentCreated(in String packageName, in IBinder agent, int userId);
void unbindBackupAgent(in ApplicationInfo appInfo);
- int getUidForIntentSender(in IIntentSender sender);
int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
boolean requireFull, in String name, in String callerPackage);
void addPackageDependency(in String packageName);
@@ -345,7 +345,6 @@
@UnsupportedAppUsage
void unregisterProcessObserver(in IProcessObserver observer);
boolean isIntentSenderTargetedToPackage(in IIntentSender sender);
- boolean isIntentSenderImmutable(in IIntentSender sender);
@UnsupportedAppUsage
void updatePersistentConfiguration(in Configuration values);
void updatePersistentConfigurationWithAttribution(in Configuration values,
@@ -375,8 +374,6 @@
void unstableProviderDied(in IBinder connection);
@UnsupportedAppUsage
boolean isIntentSenderAnActivity(in IIntentSender sender);
- boolean isIntentSenderAForegroundService(in IIntentSender sender);
- boolean isIntentSenderABroadcast(in IIntentSender sender);
/** @deprecated Use {@link startActivityAsUserWithFeature} instead */
@UnsupportedAppUsage(maxTargetSdk=29, publicAlternatives="Use {@code android.content.Context#createContextAsUser(android.os.UserHandle, int)} and {@link android.content.Context#startActivity(android.content.Intent)} instead")
int startActivityAsUser(in IApplicationThread caller, in String callingPackage,
@@ -711,5 +708,5 @@
/** Called by PendingIntent.queryIntentComponents() */
List<ResolveInfo> queryIntentComponentsForIntentSender(in IIntentSender sender, int matchFlags);
- boolean isIntentSenderAService(in IIntentSender sender);
+ int getUidProcessCapabilities(int uid, in String callingPackage);
}
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index b1c39d3..7bb5d9a 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -60,9 +60,9 @@
void onActivityForcedResizable(String packageName, int taskId, int reason);
/**
- * Called when we launched an activity that dismissed the docked stack.
+ * Called when we launched an activity that dismissed the docked task.
*/
- void onActivityDismissingDockedStack();
+ void onActivityDismissingDockedTask();
/**
* Called when an activity was requested to be launched on a secondary display but was not
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 899cdb5..f7304fb 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1371,6 +1371,18 @@
public static final String EXTRA_HANG_UP_INTENT = "android.hangUpIntent";
/**
+ * {@link #extras} key: the color used as a hint for the Answer action button of a
+ * {@link android.app.Notification.CallStyle} notification. This extra is a {@link ColorInt}.
+ */
+ public static final String EXTRA_ANSWER_COLOR = "android.answerColor";
+
+ /**
+ * {@link #extras} key: the color used as a hint for the Decline or Hang Up action button of a
+ * {@link android.app.Notification.CallStyle} notification. This extra is a {@link ColorInt}.
+ */
+ public static final String EXTRA_DECLINE_COLOR = "android.declineColor";
+
+ /**
* {@link #extras} key: whether the notification should be colorized as
* supplied to {@link Builder#setColorized(boolean)}.
*/
@@ -5444,6 +5456,11 @@
return p.allowColorization && mN.isColorized();
}
+ private boolean isCallActionColorCustomizable(StandardTemplateParams p) {
+ return isColorized(p) && mContext.getResources().getBoolean(
+ R.bool.config_callNotificationActionColorsRequireColorized);
+ }
+
private void bindSmallIcon(RemoteViews contentView, StandardTemplateParams p) {
if (mN.mSmallIcon == null && mN.icon != 0) {
mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon);
@@ -9066,6 +9083,8 @@
private PendingIntent mAnswerIntent;
private PendingIntent mDeclineIntent;
private PendingIntent mHangUpIntent;
+ private Integer mAnswerButtonColor;
+ private Integer mDeclineButtonColor;
private Icon mVerificationIcon;
private CharSequence mVerificationText;
@@ -9176,6 +9195,28 @@
}
/**
+ * Optional color to be used as a hint for the Answer action button's color.
+ * The system may change this color to ensure sufficient contrast with the background.
+ * The system may choose to disregard this hint if the notification is not colorized.
+ */
+ @NonNull
+ public CallStyle setAnswerButtonColorHint(@ColorInt int color) {
+ mAnswerButtonColor = color;
+ return this;
+ }
+
+ /**
+ * Optional color to be used as a hint for the Decline or Hang Up action button's color.
+ * The system may change this color to ensure sufficient contrast with the background.
+ * The system may choose to disregard this hint if the notification is not colorized.
+ */
+ @NonNull
+ public CallStyle setDeclineButtonColorHint(@ColorInt int color) {
+ mDeclineButtonColor = color;
+ return this;
+ }
+
+ /**
* @hide
*/
public boolean displayCustomViewInline() {
@@ -9234,40 +9275,47 @@
}
@NonNull
- private Action makeNegativeAction() {
+ private Action makeNegativeAction(@NonNull StandardTemplateParams p) {
if (mDeclineIntent == null) {
- return makeAction(R.drawable.ic_call_decline,
+ return makeAction(p, R.drawable.ic_call_decline,
R.string.call_notification_hang_up_action,
- R.color.call_notification_decline_color, mHangUpIntent);
+ mDeclineButtonColor, R.color.call_notification_decline_color,
+ mHangUpIntent);
} else {
- return makeAction(R.drawable.ic_call_decline,
+ return makeAction(p, R.drawable.ic_call_decline,
R.string.call_notification_decline_action,
- R.color.call_notification_decline_color, mDeclineIntent);
+ mDeclineButtonColor, R.color.call_notification_decline_color,
+ mDeclineIntent);
}
}
@Nullable
- private Action makeAnswerAction() {
- return mAnswerIntent == null ? null : makeAction(R.drawable.ic_call_answer,
+ private Action makeAnswerAction(@NonNull StandardTemplateParams p) {
+ return mAnswerIntent == null ? null : makeAction(p, R.drawable.ic_call_answer,
R.string.call_notification_answer_action,
- R.color.call_notification_answer_color, mAnswerIntent);
+ mAnswerButtonColor, R.color.call_notification_answer_color,
+ mAnswerIntent);
}
@NonNull
- private Action makeAction(@DrawableRes int icon, @StringRes int title,
- @ColorRes int colorRes, PendingIntent intent) {
+ private Action makeAction(@NonNull StandardTemplateParams p,
+ @DrawableRes int icon, @StringRes int title,
+ @ColorInt Integer colorInt, @ColorRes int defaultColorRes, PendingIntent intent) {
+ if (colorInt == null || !mBuilder.isCallActionColorCustomizable(p)) {
+ colorInt = mBuilder.mContext.getColor(defaultColorRes);
+ }
Action action = new Action.Builder(Icon.createWithResource("", icon),
new SpannableStringBuilder().append(mBuilder.mContext.getString(title),
- new ForegroundColorSpan(mBuilder.mContext.getColor(colorRes)),
+ new ForegroundColorSpan(colorInt),
SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE),
intent).build();
action.getExtras().putBoolean(KEY_ACTION_PRIORITY, true);
return action;
}
- private ArrayList<Action> makeActionsList() {
- final Action negativeAction = makeNegativeAction();
- final Action answerAction = makeAnswerAction();
+ private ArrayList<Action> makeActionsList(@NonNull StandardTemplateParams p) {
+ final Action negativeAction = makeNegativeAction(p);
+ final Action answerAction = makeAnswerAction(p);
ArrayList<Action> actions = new ArrayList<>(MAX_ACTION_BUTTONS);
final Action lastAction;
@@ -9356,7 +9404,7 @@
// Create the buttons for the generated actions list.
int i = 0;
- for (Action action : makeActionsList()) {
+ for (Action action : makeActionsList(p)) {
final RemoteViews button = mBuilder.generateActionButton(action, emphasizedMode, p);
if (i > 0) {
// Clear start margin from non-first buttons to reduce the gap between buttons.
@@ -9421,6 +9469,12 @@
if (mHangUpIntent != null) {
extras.putParcelable(EXTRA_HANG_UP_INTENT, mHangUpIntent);
}
+ if (mAnswerButtonColor != null) {
+ extras.putInt(EXTRA_ANSWER_COLOR, mAnswerButtonColor);
+ }
+ if (mDeclineButtonColor != null) {
+ extras.putInt(EXTRA_DECLINE_COLOR, mDeclineButtonColor);
+ }
fixTitleAndTextExtras(extras);
}
@@ -9447,6 +9501,10 @@
mAnswerIntent = extras.getParcelable(EXTRA_ANSWER_INTENT);
mDeclineIntent = extras.getParcelable(EXTRA_DECLINE_INTENT);
mHangUpIntent = extras.getParcelable(EXTRA_HANG_UP_INTENT);
+ mAnswerButtonColor = extras.containsKey(EXTRA_ANSWER_COLOR)
+ ? extras.getInt(EXTRA_ANSWER_COLOR) : null;
+ mDeclineButtonColor = extras.containsKey(EXTRA_DECLINE_COLOR)
+ ? extras.getInt(EXTRA_DECLINE_COLOR) : null;
}
/**
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 671315f..2f06bdc 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -16,6 +16,11 @@
package android.app;
+import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
+import static android.app.ActivityManager.INTENT_SENDER_BROADCAST;
+import static android.app.ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE;
+import static android.app.ActivityManager.INTENT_SENDER_SERVICE;
+
import android.Manifest.permission;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -25,6 +30,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
import android.annotation.TestApi;
+import android.app.ActivityManager.PendingIntentInfo;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
@@ -122,6 +128,9 @@
private IBinder mWhitelistToken;
private ArraySet<CancelListener> mCancelListeners;
+ // cached pending intent information
+ private @Nullable PendingIntentInfo mCachedInfo;
+
/**
* It is now required to specify either {@link #FLAG_IMMUTABLE}
* or {@link #FLAG_MUTABLE} when creating a PendingIntent.
@@ -463,7 +472,7 @@
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+ INTENT_SENDER_ACTIVITY, packageName,
context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, options, user.getIdentifier());
@@ -596,7 +605,7 @@
try {
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
+ INTENT_SENDER_ACTIVITY, packageName,
context.getAttributionTag(), null, null, requestCode, intents, resolvedTypes,
flags, options, user.getIdentifier());
return target != null ? new PendingIntent(target) : null;
@@ -650,7 +659,7 @@
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
- ActivityManager.INTENT_SENDER_BROADCAST, packageName,
+ INTENT_SENDER_BROADCAST, packageName,
context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, null, userHandle.getIdentifier());
@@ -687,7 +696,7 @@
public static PendingIntent getService(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags) {
return buildServicePendingIntent(context, requestCode, intent, flags,
- ActivityManager.INTENT_SENDER_SERVICE);
+ INTENT_SENDER_SERVICE);
}
/**
@@ -717,7 +726,7 @@
public static PendingIntent getForegroundService(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags) {
return buildServicePendingIntent(context, requestCode, intent, flags,
- ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE);
+ INTENT_SENDER_FOREGROUND_SERVICE);
}
private static PendingIntent buildServicePendingIntent(Context context, int requestCode,
@@ -1001,12 +1010,7 @@
*/
@Deprecated
public String getTargetPackage() {
- try {
- return ActivityManager.getService()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCreatorPackage();
}
/**
@@ -1029,12 +1033,7 @@
*/
@Nullable
public String getCreatorPackage() {
- try {
- return ActivityManager.getService()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getCreatorPackage();
}
/**
@@ -1056,12 +1055,7 @@
* none associated with it.
*/
public int getCreatorUid() {
- try {
- return ActivityManager.getService()
- .getUidForIntentSender(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getCreatorUid();
}
/**
@@ -1154,13 +1148,8 @@
*/
@Nullable
public UserHandle getCreatorUserHandle() {
- try {
- int uid = ActivityManager.getService()
- .getUidForIntentSender(mTarget);
- return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ int uid = getCachedInfo().getCreatorUid();
+ return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
}
/**
@@ -1180,12 +1169,7 @@
* Check if this PendingIntent is marked with {@link #FLAG_IMMUTABLE}.
*/
public boolean isImmutable() {
- try {
- return ActivityManager.getService()
- .isIntentSenderImmutable(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().isImmutable();
}
/**
@@ -1193,48 +1177,28 @@
* {@link #getActivity} or {@link #getActivities}.
*/
public boolean isActivity() {
- try {
- return ActivityManager.getService()
- .isIntentSenderAnActivity(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getIntentSenderType() == INTENT_SENDER_ACTIVITY;
}
/**
* @return TRUE if this {@link PendingIntent} was created with {@link #getForegroundService}.
*/
public boolean isForegroundService() {
- try {
- return ActivityManager.getService()
- .isIntentSenderAForegroundService(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getIntentSenderType() == INTENT_SENDER_FOREGROUND_SERVICE;
}
/**
* @return TRUE if this {@link PendingIntent} was created with {@link #getService}.
*/
public boolean isService() {
- try {
- return ActivityManager.getService()
- .isIntentSenderAService(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getIntentSenderType() == INTENT_SENDER_SERVICE;
}
/**
* @return TRUE if this {@link PendingIntent} was created with {@link #getBroadcast}.
*/
public boolean isBroadcast() {
- try {
- return ActivityManager.getService()
- .isIntentSenderABroadcast(mTarget);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return getCachedInfo().getIntentSenderType() == INTENT_SENDER_BROADCAST;
}
/**
@@ -1433,4 +1397,16 @@
*/
void onCancelled(PendingIntent intent);
}
+
+ private PendingIntentInfo getCachedInfo() {
+ if (mCachedInfo == null) {
+ try {
+ mCachedInfo = ActivityManager.getService().getInfoForIntentSender(mTarget);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ return mCachedInfo;
+ }
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index dd5a9a8..e16e40b 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -47,6 +47,7 @@
import android.app.usage.NetworkStatsManager;
import android.app.usage.StorageStatsManager;
import android.app.usage.UsageStatsManager;
+import android.apphibernation.AppHibernationManager;
import android.appwidget.AppWidgetManager;
import android.bluetooth.BluetoothManager;
import android.companion.CompanionDeviceManager;
@@ -1378,6 +1379,13 @@
IBinder b = ServiceManager.getServiceOrThrow(Context.APP_INTEGRITY_SERVICE);
return new AppIntegrityManager(IAppIntegrityManager.Stub.asInterface(b));
}});
+ registerService(Context.APP_HIBERNATION_SERVICE, AppHibernationManager.class,
+ new CachedServiceFetcher<AppHibernationManager>() {
+ @Override
+ public AppHibernationManager createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(Context.APP_HIBERNATION_SERVICE);
+ return b == null ? null : new AppHibernationManager(ctx);
+ }});
registerService(Context.DREAM_SERVICE, DreamManager.class,
new CachedServiceFetcher<DreamManager>() {
@Override
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 1e38230..f523a7d 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -43,7 +43,7 @@
@Override
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void onActivityPinned(String packageName, int userId, int taskId, int stackId)
+ public void onActivityPinned(String packageName, int userId, int taskId, int rootTaskId)
throws RemoteException {
}
@@ -66,7 +66,7 @@
@Override
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void onActivityDismissingDockedStack() throws RemoteException {
+ public void onActivityDismissingDockedTask() throws RemoteException {
}
@Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 59e5144..bb1ff60 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2746,6 +2746,32 @@
@Retention(RetentionPolicy.SOURCE)
public @interface PersonalAppsSuspensionReason {}
+ /**
+ * The default device owner type for a managed device.
+ *
+ * @hide
+ */
+ public static final int DEVICE_OWNER_TYPE_DEFAULT = 0;
+
+ /**
+ * The device owner type for a financed device.
+ *
+ * @hide
+ */
+ public static final int DEVICE_OWNER_TYPE_FINANCED = 1;
+
+ /**
+ * Different device owner types for a managed device.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "DEVICE_OWNER_TYPE_" }, value = {
+ DEVICE_OWNER_TYPE_DEFAULT,
+ DEVICE_OWNER_TYPE_FINANCED
+ })
+ public @interface DeviceOwnerType {}
+
/** @hide */
@TestApi
public static final int OPERATION_LOCK_NOW = 1;
@@ -7276,7 +7302,12 @@
/**
* @hide
*/
+ @TestApi
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.MANAGE_DEVICE_ADMINS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL
+ })
public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing,
int userHandle) {
if (mService != null) {
@@ -7453,8 +7484,10 @@
* @throws IllegalArgumentException if the package name is null or invalid
* @throws IllegalStateException If the preconditions mentioned are not met.
*/
- public boolean setDeviceOwner(ComponentName who, String ownerName, int userId)
- throws IllegalArgumentException, IllegalStateException {
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ public boolean setDeviceOwner(
+ @NonNull ComponentName who, @Nullable String ownerName, @UserIdInt int userId) {
if (mService != null) {
try {
return mService.setDeviceOwner(who, ownerName, userId);
@@ -7521,7 +7554,10 @@
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS,
+ })
public ComponentName getDeviceOwnerComponentOnAnyUser() {
return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false);
}
@@ -10477,9 +10513,10 @@
/**
* Reset record of previous system update freeze period the device went through.
- * Only callable by ADB.
* @hide
*/
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.CLEAR_FREEZE_PERIOD)
public void clearSystemUpdatePolicyFreezePeriodRecord() {
throwIfParentInstance("clearSystemUpdatePolicyFreezePeriodRecord");
if (mService == null) {
@@ -11207,9 +11244,11 @@
/**
* Makes all accumulated network logs available to DPC in a new batch.
- * Only callable by ADB. If throttled, returns time to wait in milliseconds, otherwise 0.
+ * If throttled, returns time to wait in milliseconds, otherwise 0.
* @hide
*/
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS)
public long forceNetworkLogs() {
if (mService == null) {
return -1;
@@ -11223,9 +11262,11 @@
/**
* Forces a batch of security logs to be fetched from logd and makes it available for DPC.
- * Only callable by ADB. If throttled, returns time to wait in milliseconds, otherwise 0.
+ * If throttled, returns time to wait in milliseconds, otherwise 0.
* @hide
*/
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS)
public long forceSecurityLogs() {
if (mService == null) {
return 0;
@@ -11657,7 +11698,10 @@
* @throws SecurityException if the caller is not shell / root or the admin package
* isn't a test application see {@link ApplicationInfo#FLAG_TEST_APP}.
*/
- public void forceRemoveActiveAdmin(ComponentName adminReceiver, int userHandle) {
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+ public void forceRemoveActiveAdmin(
+ @NonNull ComponentName adminReceiver, @UserIdInt int userHandle) {
try {
mService.forceRemoveActiveAdmin(adminReceiver, userHandle);
} catch (RemoteException re) {
@@ -12727,8 +12771,11 @@
*
* @hide
*/
- @RequiresPermission(value = android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED,
- conditional = true)
+ @TestApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED,
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+ }, conditional = true)
public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull ComponentName who) {
if (mService == null) {
return;
@@ -13460,6 +13507,57 @@
}
/**
+ * Sets the device owner type for a managed device (e.g. financed device).
+ *
+ * @param admin The {@link DeviceAdminReceiver} that is the device owner.
+ * @param deviceOwnerType The device owner type is set to. Use
+ * {@link #DEVICE_OWNER_TYPE_DEFAULT} for the default device owner type. Use
+ * {@link #DEVICE_OWNER_TYPE_FINANCED} for the financed device owner type.
+ *
+ * @throws IllegalStateException When admin is not the device owner, or there is no device
+ * owner, or attempting to set the device owner type again for the same admin.
+ * @throws SecurityException If the caller does not have the permission
+ * {@link permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}.
+ *
+ * @hide
+ */
+ public void setDeviceOwnerType(@NonNull ComponentName admin,
+ @DeviceOwnerType int deviceOwnerType) {
+ throwIfParentInstance("setDeviceOwnerType");
+ if (mService != null) {
+ try {
+ mService.setDeviceOwnerType(admin, deviceOwnerType);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
+ * Returns the device owner type for the admin used in
+ * {@link #setDeviceOwnerType(ComponentName, int)}. {@link #DEVICE_OWNER_TYPE_DEFAULT}
+ * would be returned when the device owner type is not set for the device owner admin.
+ *
+ * @param admin The {@link DeviceAdminReceiver} that is the device owner.
+ *
+ * @throws IllegalStateException When admin is not the device owner or there is no device owner.
+ *
+ * @hide
+ */
+ @DeviceOwnerType
+ public int getDeviceOwnerType(@NonNull ComponentName admin) {
+ throwIfParentInstance("getDeviceOwnerType");
+ if (mService != null) {
+ try {
+ return mService.getDeviceOwnerType(admin);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return DEVICE_OWNER_TYPE_DEFAULT;
+ }
+
+ /**
* Called by device owner or profile owner of an organization-owned managed profile to
* enable or disable USB data signaling for the device. When disabled, USB data connections
* (except from charging functions) are prohibited.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 8a87b16..ac1592d 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -503,6 +503,9 @@
UserHandle createAndProvisionManagedProfile(in ManagedProfileProvisioningParams provisioningParams, in String callerPackage);
void provisionFullyManagedDevice(in FullyManagedDeviceProvisioningParams provisioningParams, in String callerPackage);
+ void setDeviceOwnerType(in ComponentName admin, in int deviceOwnerType);
+ int getDeviceOwnerType(in ComponentName admin);
+
void resetDefaultCrossProfileIntentFilters(int userId);
boolean canAdminGrantSensorsPermissionsForUser(int userId);
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 673de8f..dae565e 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -361,36 +361,7 @@
try {
// All packages, current transport
IRestoreSession binder =
- sService.beginRestoreSessionForUser(mContext.getUserId(), null, null,
- OperationType.BACKUP);
- if (binder != null) {
- session = new RestoreSession(mContext, binder);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "beginRestoreSession() couldn't connect");
- }
- }
- return session;
- }
-
- /**
- * Begin the process of restoring data from backup. See the
- * {@link android.app.backup.RestoreSession} class for documentation on that process.
- *
- * @param operationType Type of the operation, see {@link OperationType}
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BACKUP)
- public RestoreSession beginRestoreSession(@OperationType int operationType) {
- RestoreSession session = null;
- checkServiceBinder();
- if (sService != null) {
- try {
- // All packages, current transport
- IRestoreSession binder =
- sService.beginRestoreSessionForUser(mContext.getUserId(), null, null,
- operationType);
+ sService.beginRestoreSessionForUser(mContext.getUserId(), null, null);
if (binder != null) {
session = new RestoreSession(mContext, binder);
}
@@ -801,7 +772,7 @@
@SystemApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public int requestBackup(String[] packages, BackupObserver observer) {
- return requestBackup(packages, observer, null, 0, OperationType.BACKUP);
+ return requestBackup(packages, observer, null, 0);
}
/**
@@ -826,31 +797,6 @@
@RequiresPermission(android.Manifest.permission.BACKUP)
public int requestBackup(String[] packages, BackupObserver observer,
BackupManagerMonitor monitor, int flags) {
- return requestBackup(packages, observer, monitor, flags, OperationType.BACKUP);
- }
-
- /**
- * Request an immediate backup, providing an observer to which results of the backup operation
- * will be published. The Android backup system will decide for each package whether it will
- * be full app data backup or key/value-pair-based backup.
- *
- * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all
- * provided packages using the remote transport.
- *
- * @param packages List of package names to backup.
- * @param observer The {@link BackupObserver} to receive callbacks during the backup
- * operation. Could be {@code null}.
- * @param monitor The {@link BackupManagerMonitorWrapper} to receive callbacks of important
- * events during the backup operation. Could be {@code null}.
- * @param flags {@link #FLAG_NON_INCREMENTAL_BACKUP}.
- * @param operationType {@link OperationType}
- * @return {@link BackupManager#SUCCESS} on success; nonzero on error.
- * @throws IllegalArgumentException on null or empty {@code packages} param.
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.BACKUP)
- public int requestBackup(String[] packages, BackupObserver observer,
- BackupManagerMonitor monitor, int flags, @OperationType int operationType) {
checkServiceBinder();
if (sService != null) {
try {
@@ -860,8 +806,7 @@
BackupManagerMonitorWrapper monitorWrapper = monitor == null
? null
: new BackupManagerMonitorWrapper(monitor);
- return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags,
- operationType);
+ return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags);
} catch (RemoteException e) {
Log.e(TAG, "requestBackup() couldn't connect");
}
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index f7ed6f1f..3701ea8 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -19,8 +19,10 @@
import static android.app.backup.BackupManager.OperationType;
import android.annotation.Nullable;
+import android.annotation.StringDef;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.XmlResourceParser;
import android.os.ParcelFileDescriptor;
@@ -33,6 +35,7 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -93,6 +96,15 @@
public static final String FLAG_REQUIRED_FAKE_CLIENT_SIDE_ENCRYPTION =
"fakeClientSideEncryption";
+ @StringDef({
+ ConfigSection.CLOUD_BACKUP,
+ ConfigSection.DEVICE_TRANSFER
+ })
+ private @interface ConfigSection {
+ String CLOUD_BACKUP = "cloud-backup";
+ String DEVICE_TRANSFER = "device-transfer";
+ }
+
/**
* Identify {@link BackupScheme} object by package and operation type
* (see {@link OperationType}) it corresponds to.
@@ -273,6 +285,7 @@
private final static String TAG_INCLUDE = "include";
private final static String TAG_EXCLUDE = "exclude";
+ final int mDataExtractionRules;
final int mFullBackupContent;
@OperationType final int mOperationType;
final PackageManager mPackageManager;
@@ -394,7 +407,10 @@
ArraySet<PathWithRequiredFlags> mExcludes;
BackupScheme(Context context, @OperationType int operationType) {
- mFullBackupContent = context.getApplicationInfo().fullBackupContent;
+ ApplicationInfo applicationInfo = context.getApplicationInfo();
+
+ mDataExtractionRules = applicationInfo.dataExtractionRulesRes;
+ mFullBackupContent = applicationInfo.fullBackupContent;
mOperationType = operationType;
mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
mPackageManager = context.getPackageManager();
@@ -468,34 +484,98 @@
mIncludes = new ArrayMap<String, Set<PathWithRequiredFlags>>();
mExcludes = new ArraySet<PathWithRequiredFlags>();
- if (mFullBackupContent == 0) {
- // android:fullBackupContent="true" which means that we'll do everything.
+ if (mFullBackupContent == 0 && mDataExtractionRules == 0) {
+ // No scheme specified via either new or legacy config, will copy everything.
if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) {
Log.v(FullBackup.TAG_XML_PARSER, "android:fullBackupContent - \"true\"");
}
} else {
- // android:fullBackupContent="@xml/some_resource".
+ // Scheme is present.
if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) {
- Log.v(FullBackup.TAG_XML_PARSER,
- "android:fullBackupContent - found xml resource");
+ Log.v(FullBackup.TAG_XML_PARSER, "Found xml scheme: "
+ + "android:fullBackupContent=" + mFullBackupContent
+ + "; android:dataExtractionRules=" + mDataExtractionRules);
}
- XmlResourceParser parser = null;
+
try {
- parser = mPackageManager
- .getResourcesForApplication(mPackageName)
- .getXml(mFullBackupContent);
- parseBackupSchemeFromXmlLocked(parser, mExcludes, mIncludes);
+ parseSchemeForOperationType(mOperationType);
} catch (PackageManager.NameNotFoundException e) {
// Throw it as an IOException
throw new IOException(e);
- } finally {
- if (parser != null) {
- parser.close();
- }
}
}
}
+ private void parseSchemeForOperationType(@OperationType int operationType)
+ throws PackageManager.NameNotFoundException, IOException, XmlPullParserException {
+ String configSection = getConfigSectionForOperationType(operationType);
+ if (configSection == null) {
+ Slog.w(TAG, "Given operation type isn't supported by backup scheme: "
+ + operationType);
+ return;
+ }
+
+ if (mDataExtractionRules != 0) {
+ // New config is present. Use it if it has configuration for this operation
+ // type.
+ try (XmlResourceParser parser = getParserForResource(mDataExtractionRules)) {
+ parseNewBackupSchemeFromXmlLocked(parser, configSection, mExcludes, mIncludes);
+ }
+ if (!mExcludes.isEmpty() || !mIncludes.isEmpty()) {
+ // Found configuration in the new config, we will use it.
+ return;
+ }
+ }
+
+ // TODO(b/180523564): Ignore the old config for apps targeting Android S+ during D2D.
+
+ if (mFullBackupContent != 0) {
+ // Fall back to the old config.
+ try (XmlResourceParser parser = getParserForResource(mFullBackupContent)) {
+ parseBackupSchemeFromXmlLocked(parser, mExcludes, mIncludes);
+ }
+ }
+ }
+
+ @Nullable
+ private String getConfigSectionForOperationType(@OperationType int operationType) {
+ switch (operationType) {
+ case OperationType.BACKUP:
+ return ConfigSection.CLOUD_BACKUP;
+ case OperationType.MIGRATION:
+ return ConfigSection.DEVICE_TRANSFER;
+ default:
+ return null;
+ }
+ }
+
+ private XmlResourceParser getParserForResource(int resourceId)
+ throws PackageManager.NameNotFoundException {
+ return mPackageManager
+ .getResourcesForApplication(mPackageName)
+ .getXml(resourceId);
+ }
+
+ private void parseNewBackupSchemeFromXmlLocked(XmlPullParser parser,
+ @ConfigSection String configSection,
+ Set<PathWithRequiredFlags> excludes,
+ Map<String, Set<PathWithRequiredFlags>> includes)
+ throws IOException, XmlPullParserException {
+ verifyTopLevelTag(parser, "data-extraction-rules");
+
+ int event;
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (event != XmlPullParser.START_TAG || !configSection.equals(parser.getName())) {
+ continue;
+ }
+
+ // TODO(b/180523028): Parse required attributes for rules (e.g. encryption).
+ parseRules(parser, excludes, includes, Optional.of(0), configSection);
+ }
+
+ logParsingResults(excludes, includes);
+ }
+
@VisibleForTesting
public void parseBackupSchemeFromXmlLocked(XmlPullParser parser,
Set<PathWithRequiredFlags> excludes,
@@ -503,7 +583,7 @@
throws IOException, XmlPullParserException {
verifyTopLevelTag(parser, "full-backup-content");
- parseRules(parser, excludes, includes, Optional.empty());
+ parseRules(parser, excludes, includes, Optional.empty(), "full-backup-content");
logParsingResults(excludes, includes);
}
@@ -532,10 +612,12 @@
private void parseRules(XmlPullParser parser,
Set<PathWithRequiredFlags> excludes,
Map<String, Set<PathWithRequiredFlags>> includes,
- Optional<Integer> maybeRequiredFlags)
+ Optional<Integer> maybeRequiredFlags,
+ String endingTag)
throws IOException, XmlPullParserException {
int event;
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ while ((event = parser.next()) != XmlPullParser.END_DOCUMENT
+ && !parser.getName().equals(endingTag)) {
switch (event) {
case XmlPullParser.START_TAG:
validateInnerTagContents(parser);
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index e1bbc08..bf5be95 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -547,11 +547,9 @@
* set can be restored.
* @param transportID The name of the transport to use for the restore operation.
* May be null, in which case the current active transport is used.
- * @param operationType Type of the operation, see {@link BackupManager#OperationType}
* @return An interface to the restore session, or null on error.
*/
- IRestoreSession beginRestoreSessionForUser(int userId, String packageName, String transportID,
- int operationType);
+ IRestoreSession beginRestoreSessionForUser(int userId, String packageName, String transportID);
/**
* Notify the backup manager that a BackupAgent has completed the operation
@@ -680,7 +678,7 @@
* {@link android.app.backup.IBackupManager.requestBackupForUser} for the calling user id.
*/
int requestBackup(in String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor,
- int flags, int operationType);
+ int flags);
/**
* Cancel all running backups. After this call returns, no currently running backups will
diff --git a/core/java/android/app/time/LocationTimeZoneManager.java b/core/java/android/app/time/LocationTimeZoneManager.java
index 71a800f..066aada 100644
--- a/core/java/android/app/time/LocationTimeZoneManager.java
+++ b/core/java/android/app/time/LocationTimeZoneManager.java
@@ -37,7 +37,7 @@
/**
* The name of the service for shell commands
*/
- public static final String SHELL_COMMAND_SERVICE_NAME = "location_time_zone_manager";
+ public static final String SERVICE_NAME = "location_time_zone_manager";
/**
* A shell command that starts the service (after stop).
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 4277292..fc54c71 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -40,6 +40,7 @@
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -92,7 +93,10 @@
int mLayoutId = -1;
private InteractionHandler mInteractionHandler;
private boolean mOnLightBackground;
- PointF mCurrentSize = null;
+ private PointF mCurrentSize = null;
+ private RemoteViews.ColorResources mColorResources = null;
+ // Stores the last remote views last inflated.
+ private RemoteViews mLastInflatedRemoteViews = null;
private Executor mAsyncExecutor;
private CancellationSignal mLastExecutionSignal;
@@ -358,7 +362,7 @@
PointF newSize = new PointF(size.x - xPaddingDips, size.y - yPaddingDips);
if (!newSize.equals(mCurrentSize)) {
mCurrentSize = newSize;
- mLayoutId = -1; // Prevents recycling the view.
+ reapplyLastRemoteViews();
}
}
@@ -368,7 +372,7 @@
public void clearCurrentSize() {
if (mCurrentSize != null) {
mCurrentSize = null;
- mLayoutId = -1;
+ reapplyLastRemoteViews();
}
}
@@ -477,10 +481,18 @@
* AppWidget provider. Will animate into these new views as needed
*/
public void updateAppWidget(RemoteViews remoteViews) {
+ this.mLastInflatedRemoteViews = remoteViews;
applyRemoteViews(remoteViews, true);
}
/**
+ * Reapply the last inflated remote views, or the default view is none was inflated.
+ */
+ private void reapplyLastRemoteViews() {
+ applyRemoteViews(mLastInflatedRemoteViews, true);
+ }
+
+ /**
* @hide
*/
protected void applyRemoteViews(RemoteViews remoteViews, boolean useAsyncIfPossible) {
@@ -518,7 +530,8 @@
// layout matches, try recycling it
if (content == null && layoutId == mLayoutId) {
try {
- remoteViews.reapply(mContext, mView, mInteractionHandler);
+ remoteViews.reapply(mContext, mView, mInteractionHandler, mCurrentSize,
+ mColorResources);
content = mView;
recycled = true;
if (LOGD) Log.d(TAG, "was able to recycle existing layout");
@@ -530,7 +543,8 @@
// Try normal RemoteView inflation
if (content == null) {
try {
- content = remoteViews.apply(mContext, this, mInteractionHandler, mCurrentSize);
+ content = remoteViews.apply(mContext, this, mInteractionHandler,
+ mCurrentSize, mColorResources);
if (LOGD) Log.d(TAG, "had to inflate new layout");
} catch (RuntimeException e) {
exception = e;
@@ -583,7 +597,8 @@
mAsyncExecutor,
new ViewApplyListener(remoteViews, layoutId, true),
mInteractionHandler,
- mCurrentSize);
+ mCurrentSize,
+ mColorResources);
} catch (Exception e) {
// Reapply failed. Try apply
}
@@ -594,7 +609,8 @@
mAsyncExecutor,
new ViewApplyListener(remoteViews, layoutId, false),
mInteractionHandler,
- mCurrentSize);
+ mCurrentSize,
+ mColorResources);
}
}
@@ -662,9 +678,13 @@
protected Context getRemoteContext() {
try {
// Return if cloned successfully, otherwise default
- return mContext.createApplicationContext(
+ Context newContext = mContext.createApplicationContext(
mInfo.providerInfo.applicationInfo,
Context.CONTEXT_RESTRICTED);
+ if (mColorResources != null) {
+ mColorResources.apply(newContext);
+ }
+ return newContext;
} catch (NameNotFoundException e) {
Log.e(TAG, "Package name " + mInfo.providerInfo.packageName + " not found");
return mContext;
@@ -819,4 +839,37 @@
}
};
}
+
+ /**
+ * Set the dynamically overloaded color resources.
+ *
+ * {@code colorMapping} maps a predefined set of color resources to their ARGB
+ * representation. Any entry not in the predefined set of colors will be ignored.
+ *
+ * Calling this method will trigger a full re-inflation of the App Widget.
+ *
+ * The color resources that can be overloaded are the ones whose name is prefixed with
+ * {@code system_primary_}, {@code system_secondary_} or {@code system_neutral_}, for example
+ * {@link android.R.color#system_primary_500}.
+ */
+ public void setColorResources(@NonNull SparseIntArray colorMapping) {
+ mColorResources = RemoteViews.ColorResources.create(mContext, colorMapping);
+ mLayoutId = -1;
+ reapplyLastRemoteViews();
+ }
+
+ /**
+ * Reset the dynamically overloaded resources, reverting to the default values for
+ * all the colors.
+ *
+ * If colors were defined before, calling this method will trigger a full re-inflation of the
+ * App Widget.
+ */
+ public void resetColorResources() {
+ if (mColorResources != null) {
+ mColorResources = null;
+ mLayoutId = -1;
+ reapplyLastRemoteViews();
+ }
+ }
}
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index aac8710..38919f6 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,6 +23,8 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
+import android.annotation.TestApi;
+import android.annotation.UserIdInt;
import android.app.IServiceConnection;
import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
@@ -1095,7 +1097,9 @@
*
* @hide
*/
- public void setBindAppWidgetPermission(String packageName, int userId, boolean permission) {
+ @TestApi
+ public void setBindAppWidgetPermission(
+ @NonNull String packageName, @UserIdInt int userId, boolean permission) {
if (mService == null) {
return;
}
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index d893a5e..6ac1c1a 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -332,12 +332,13 @@
/**
* Resource id for the description of the AppWidget.
+ *
* <p>This field corresponds to the <code>android:description</code> attribute in the AppWidget
* meta-data file.
*/
@SuppressLint("MutableBareField")
@IdRes
- public int descriptionResource;
+ public int descriptionRes;
/**
* Flags indicating various features supported by the widget. These are hints to the widget
@@ -385,7 +386,7 @@
this.widgetCategory = in.readInt();
this.providerInfo = in.readTypedObject(ActivityInfo.CREATOR);
this.widgetFeatures = in.readInt();
- this.descriptionResource = in.readInt();
+ this.descriptionRes = in.readInt();
}
/**
@@ -442,14 +443,22 @@
return loadDrawable(context, density, previewImage, false);
}
- /** Loads localized description for the app widget. */
+ /**
+ * Loads localized description for the app widget.
+ *
+ * <p>Description is intended to be displayed in the UI of the widget picker.
+ *
+ * @param context Context for accessing resources.
+ *
+ * @return CharSequence for app widget description for the current locale.
+ */
@Nullable
- public final String loadDescription(@NonNull Context context) {
- if (ResourceId.isValid(descriptionResource)) {
+ public final CharSequence loadDescription(@NonNull Context context) {
+ if (ResourceId.isValid(descriptionRes)) {
return context.getPackageManager()
.getText(
providerInfo.packageName,
- descriptionResource,
+ descriptionRes,
providerInfo.applicationInfo)
.toString()
.trim();
@@ -499,7 +508,7 @@
out.writeInt(this.widgetCategory);
out.writeTypedObject(this.providerInfo, flags);
out.writeInt(this.widgetFeatures);
- out.writeInt(this.descriptionResource);
+ out.writeInt(this.descriptionRes);
}
@Override
@@ -528,7 +537,7 @@
that.widgetCategory = this.widgetCategory;
that.providerInfo = this.providerInfo;
that.widgetFeatures = this.widgetFeatures;
- that.descriptionResource = this.descriptionResource;
+ that.descriptionRes = this.descriptionRes;
return that;
}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index cd91aa9..53aaae0 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -943,12 +943,13 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
- public boolean setBufferMillis(@BluetoothCodecConfig.SourceCodecType int codec, int value) {
- if (VDBG) log("setBufferMillis(" + codec + ", " + value + ")");
+ public boolean setBufferLengthMillis(@BluetoothCodecConfig.SourceCodecType int codec,
+ int value) {
+ if (VDBG) log("setBufferLengthMillis(" + codec + ", " + value + ")");
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
- return service.setBufferMillis(codec, value);
+ return service.setBufferLengthMillis(codec, value);
}
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ec46da0..8d41572 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3654,12 +3654,12 @@
}
@Override
- public void onDeviceDisconnected(BluetoothDevice device) {
+ public void onDeviceDisconnected(BluetoothDevice device, int hciReason) {
for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
mBluetoothConnectionCallbackExecutorMap.entrySet()) {
BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
Executor executor = callbackExecutorEntry.getValue();
- executor.execute(() -> callback.onDeviceDisconnected(device));
+ executor.execute(() -> callback.onDeviceDisconnected(device, hciReason));
}
}
};
@@ -3764,8 +3764,155 @@
/**
* Callback triggered when a bluetooth device (classic or BLE) is disconnected
* @param device is the disconnected bluetooth device
+ * @param reason is the disconnect reason
*/
- public void onDeviceDisconnected(BluetoothDevice device) {}
+ public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {}
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "REASON_" }, value = {
+ REASON_UNKNOWN,
+ REASON_LOCAL_REQUEST,
+ REASON_REMOTE_REQUEST,
+ REASON_LOCAL_ERROR,
+ REASON_REMOTE_ERROR,
+ REASON_TIMEOUT,
+ REASON_SECURITY,
+ REASON_SYSTEM_POLICY,
+ REASON_RESOURCE_LIMIT_REACHED,
+ REASON_CONNECTION_EXISTS,
+ REASON_BAD_PARAMETERS})
+ public @interface DisconnectReason {}
+
+ /**
+ * Indicates that the ACL disconnected due to an unknown reason.
+ */
+ public static final int REASON_UNKNOWN = 0;
+
+ /**
+ * Indicates that the ACL disconnected due to an explicit request from the local device.
+ * <p>
+ * Example cause: This is a normal disconnect reason, e.g., user/app initiates
+ * disconnection.
+ */
+ public static final int REASON_LOCAL_REQUEST = 1;
+
+ /**
+ * Indicates that the ACL disconnected due to an explicit request from the remote device.
+ * <p>
+ * Example cause: This is a normal disconnect reason, e.g., user/app initiates
+ * disconnection.
+ * <p>
+ * Example solution: The app can also prompt the user to check their remote device.
+ */
+ public static final int REASON_REMOTE_REQUEST = 2;
+
+ /**
+ * Generic disconnect reason indicating the ACL disconnected due to an error on the local
+ * device.
+ * <p>
+ * Example solution: Prompt the user to check their local device (e.g., phone, car
+ * headunit).
+ */
+ public static final int REASON_LOCAL_ERROR = 3;
+
+ /**
+ * Generic disconnect reason indicating the ACL disconnected due to an error on the remote
+ * device.
+ * <p>
+ * Example solution: Prompt the user to check their remote device (e.g., headset, car
+ * headunit, watch).
+ */
+ public static final int REASON_REMOTE_ERROR = 4;
+
+ /**
+ * Indicates that the ACL disconnected due to a timeout.
+ * <p>
+ * Example cause: remote device might be out of range.
+ * <p>
+ * Example solution: Prompt user to verify their remote device is on or in
+ * connection/pairing mode.
+ */
+ public static final int REASON_TIMEOUT = 5;
+
+ /**
+ * Indicates that the ACL disconnected due to link key issues.
+ * <p>
+ * Example cause: Devices are either unpaired or remote device is refusing our pairing
+ * request.
+ * <p>
+ * Example solution: Prompt user to unpair and pair again.
+ */
+ public static final int REASON_SECURITY = 6;
+
+ /**
+ * Indicates that the ACL disconnected due to the local device's system policy.
+ * <p>
+ * Example cause: privacy policy, power management policy, permissions, etc.
+ * <p>
+ * Example solution: Prompt the user to check settings, or check with their system
+ * administrator (e.g. some corp-managed devices do not allow OPP connection).
+ */
+ public static final int REASON_SYSTEM_POLICY = 7;
+
+ /**
+ * Indicates that the ACL disconnected due to resource constraints, either on the local
+ * device or the remote device.
+ * <p>
+ * Example cause: controller is busy, memory limit reached, maximum number of connections
+ * reached.
+ * <p>
+ * Example solution: The app should wait and try again. If still failing, prompt the user
+ * to disconnect some devices, or toggle Bluetooth on the local and/or the remote device.
+ */
+ public static final int REASON_RESOURCE_LIMIT_REACHED = 8;
+
+ /**
+ * Indicates that the ACL disconnected because another ACL connection already exists.
+ */
+ public static final int REASON_CONNECTION_EXISTS = 9;
+
+ /**
+ * Indicates that the ACL disconnected due to incorrect parameters passed in from the app.
+ * <p>
+ * Example solution: Change parameters and try again. If error persists, the app can report
+ * telemetry and/or log the error in a bugreport.
+ */
+ public static final int REASON_BAD_PARAMETERS = 10;
+
+ /**
+ * Returns human-readable strings corresponding to {@link DisconnectReason}.
+ */
+ public static String disconnectReasonText(@DisconnectReason int reason) {
+ switch (reason) {
+ case REASON_UNKNOWN:
+ return "Reason unknown";
+ case REASON_LOCAL_REQUEST:
+ return "Local request";
+ case REASON_REMOTE_REQUEST:
+ return "Remote request";
+ case REASON_LOCAL_ERROR:
+ return "Local error";
+ case REASON_REMOTE_ERROR:
+ return "Remote error";
+ case REASON_TIMEOUT:
+ return "Timeout";
+ case REASON_SECURITY:
+ return "Security";
+ case REASON_SYSTEM_POLICY:
+ return "System policy";
+ case REASON_RESOURCE_LIMIT_REACHED:
+ return "Resource constrained";
+ case REASON_CONNECTION_EXISTS:
+ return "Connection already exists";
+ case REASON_BAD_PARAMETERS:
+ return "Bad parameters";
+ default:
+ return "Unrecognized disconnect reason: " + reason;
+ }
+ }
}
/**
diff --git a/core/java/android/bluetooth/BufferConstraints.java b/core/java/android/bluetooth/BufferConstraints.java
index 7e5ec1e..97d9723 100644
--- a/core/java/android/bluetooth/BufferConstraints.java
+++ b/core/java/android/bluetooth/BufferConstraints.java
@@ -90,7 +90,7 @@
* @hide
*/
@SystemApi
- public @Nullable BufferConstraint getCodec(@BluetoothCodecConfig.SourceCodecType int codec) {
+ public @Nullable BufferConstraint forCodec(@BluetoothCodecConfig.SourceCodecType int codec) {
return mBufferConstraints.get(codec);
}
}
diff --git a/core/java/android/companion/DeviceNotAssociatedException.java b/core/java/android/companion/DeviceNotAssociatedException.java
index bebb6c9..f8a7a7c 100644
--- a/core/java/android/companion/DeviceNotAssociatedException.java
+++ b/core/java/android/companion/DeviceNotAssociatedException.java
@@ -23,7 +23,7 @@
* An exception for a case when a given device was not
* {@link CompanionDeviceManager#associate associated} to the calling app.
*/
-public class DeviceNotAssociatedException extends Exception {
+public class DeviceNotAssociatedException extends RuntimeException {
/** @hide */
public DeviceNotAssociatedException(@Nullable String deviceName) {
super("Device not associated with the current app: " + deviceName);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 46d8900..230c985 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -132,8 +132,11 @@
public static final String SYNC_EXTRAS_ACCOUNT = "account";
/**
- * If this extra is set to true, the sync request will be scheduled
- * at the front of the sync request queue and without any delay
+ * If this extra is set to true, the sync request will be scheduled at the front of the
+ * sync request queue, but it is still subject to JobScheduler quota and throttling due to
+ * App Standby buckets.
+ *
+ * <p>This is different from {@link #SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB}.
*/
public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
@@ -145,6 +148,29 @@
public static final String SYNC_EXTRAS_REQUIRE_CHARGING = "require_charging";
/**
+ * Run this sync operation as an "expedited job"
+ * (see {@link android.app.job.JobInfo.Builder#setExpedited(boolean)}).
+ * Normally (if this flag isn't specified), sync operations are executed as regular
+ * {@link android.app.job.JobService} jobs.
+ *
+ * <p> Because Expedited Jobs have various restrictions compared to regular jobs, this flag
+ * cannot be combined with certain other flags, otherwise an
+ * <code>IllegalArgumentException</code> will be thrown. Notably, because Expedited Jobs do not
+ * support various constraints, the following restriction apply:
+ * <ul>
+ * <li>Can't be used with {@link #SYNC_EXTRAS_REQUIRE_CHARGING}
+ * <li>Can't be used with {@link #SYNC_EXTRAS_EXPEDITED}
+ * <li>Can't be used on periodic syncs.
+ * <li>When an expedited-job-sync fails and a retry is scheduled, the retried sync will be
+ * scheduled as a regular job unless {@link #SYNC_EXTRAS_IGNORE_BACKOFF} is set.
+ * </ul>
+ *
+ * <p>This is different from {@link #SYNC_EXTRAS_EXPEDITED}.
+ */
+ @SuppressLint("IntentName")
+ public static final String SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB = "schedule_as_expedited_job";
+
+ /**
* @deprecated instead use
* {@link #SYNC_EXTRAS_MANUAL}
*/
@@ -3220,6 +3246,18 @@
}
/**
+ * {@hide}
+ * Helper function to throw an <code>IllegalArgumentException</code> if any illegal
+ * extras were set for a sync scheduled as an expedited job.
+ *
+ * @param extras bundle to validate.
+ */
+ public static boolean hasInvalidScheduleAsEjExtras(Bundle extras) {
+ return extras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING)
+ || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED);
+ }
+
+ /**
* Specifies that a sync should be requested with the specified the account, authority,
* and extras at the given frequency. If there is already another periodic sync scheduled
* with the account, authority and extras then a new periodic sync won't be added, instead
@@ -3233,7 +3271,8 @@
* Periodic syncs are not allowed to have any of {@link #SYNC_EXTRAS_DO_NOT_RETRY},
* {@link #SYNC_EXTRAS_IGNORE_BACKOFF}, {@link #SYNC_EXTRAS_IGNORE_SETTINGS},
* {@link #SYNC_EXTRAS_INITIALIZE}, {@link #SYNC_EXTRAS_FORCE},
- * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL} set to true.
+ * {@link #SYNC_EXTRAS_EXPEDITED}, {@link #SYNC_EXTRAS_MANUAL},
+ * {@link #SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB} set to true.
* If any are supplied then an {@link IllegalArgumentException} will be thrown.
*
* <p>This method requires the caller to hold the permission
@@ -3273,16 +3312,14 @@
* @param extras bundle to validate.
*/
public static boolean invalidPeriodicExtras(Bundle extras) {
- if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)
+ return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)
|| extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
|| extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)
|| extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false)
|| extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)
|| extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)
- || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
- return true;
- }
- return false;
+ || extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)
+ || extras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false);
}
/**
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e20f706..f3a4e1f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -370,6 +370,25 @@
/*********** Hidden flags below this line ***********/
/**
+ * Flag for {@link #bindService}: allow the process hosting the target service to be treated
+ * as if it's as important as a perceptible app to the user and avoid the oom killer killing
+ * this process in low memory situations until there aren't any other processes left but the
+ * ones which are user-perceptible.
+ *
+ * @hide
+ */
+ public static final int BIND_ALMOST_PERCEPTIBLE = 0x000010000;
+
+ /**
+ * Flag for {@link #bindService}: allow the process hosting the target service to gain
+ * {@link ActivityManager#PROCESS_CAPABILITY_NETWORK}, which allows it be able
+ * to access network regardless of any power saving restrictions.
+ *
+ * @hide
+ */
+ public static final int BIND_ALLOW_NETWORK_ACCESS = 0x00020000;
+
+ /**
* Flag for {@link #bindService}: allow background foreground service starts from the bound
* service's process.
* This flag is only respected if the caller is holding
@@ -6674,15 +6693,6 @@
}
/**
- * Indicates if this context is a visual context such as {@link android.app.Activity} or
- * a context created from {@link #createWindowContext(int, Bundle)}.
- * @hide
- */
- public boolean isUiContext() {
- throw new RuntimeException("Not implemented. Must override in a subclass.");
- }
-
- /**
* Returns {@code true} if the context is a UI context which can access UI components such as
* {@link WindowManager}, {@link android.view.LayoutInflater LayoutInflater} or
* {@link android.app.WallpaperManager WallpaperManager}. Accessing UI components from non-UI
@@ -6694,12 +6704,16 @@
* {@link #createWindowContext(int, Bundle)} or
* {@link android.inputmethodservice.InputMethodService InputMethodService}
* </p>
+ * <p>
+ * Note that even if it is allowed programmatically, it is not suggested to override this
+ * method to bypass {@link android.os.strictmode.IncorrectContextUseViolation} verification.
+ * </p>
*
* @see #getDisplay()
* @see #getSystemService(String)
* @see android.os.StrictMode.VmPolicy.Builder#detectIncorrectContextUse()
*/
- public static boolean isUiContext(@NonNull Context context) {
- return context.isUiContext();
+ public boolean isUiContext() {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
}
}
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 858d1e4..b1252fd 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Handler;
@@ -60,6 +61,9 @@
private final IIntentSender mTarget;
IBinder mWhitelistToken;
+ // cached pending intent information
+ private @Nullable PendingIntentInfo mCachedInfo;
+
/**
* Exception thrown when trying to send through a PendingIntent that
* has been canceled or is otherwise no longer able to execute the request.
@@ -209,13 +213,7 @@
*/
@Deprecated
public String getTargetPackage() {
- try {
- return ActivityManager.getService()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- // Should never happen.
- return null;
- }
+ return getCreatorPackage();
}
/**
@@ -228,13 +226,7 @@
* none associated with it.
*/
public String getCreatorPackage() {
- try {
- return ActivityManager.getService()
- .getPackageForIntentSender(mTarget);
- } catch (RemoteException e) {
- // Should never happen.
- return null;
- }
+ return getCachedInfo().getCreatorPackage();
}
/**
@@ -247,13 +239,7 @@
* none associated with it.
*/
public int getCreatorUid() {
- try {
- return ActivityManager.getService()
- .getUidForIntentSender(mTarget);
- } catch (RemoteException e) {
- // Should never happen.
- return -1;
- }
+ return getCachedInfo().getCreatorUid();
}
/**
@@ -268,14 +254,8 @@
* none associated with it.
*/
public UserHandle getCreatorUserHandle() {
- try {
- int uid = ActivityManager.getService()
- .getUidForIntentSender(mTarget);
- return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
- } catch (RemoteException e) {
- // Should never happen.
- return null;
- }
+ int uid = getCachedInfo().getCreatorUid();
+ return uid > 0 ? new UserHandle(UserHandle.getUserId(uid)) : null;
}
/**
@@ -384,4 +364,16 @@
public IntentSender(IBinder target) {
mTarget = IIntentSender.Stub.asInterface(target);
}
+
+ private PendingIntentInfo getCachedInfo() {
+ if (mCachedInfo == null) {
+ try {
+ mCachedInfo = ActivityManager.getService().getInfoForIntentSender(mTarget);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ return mCachedInfo;
+ }
}
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 9e568a4..e1e6f75 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -17,6 +17,7 @@
package android.content;
import android.accounts.Account;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
@@ -58,6 +59,8 @@
private final boolean mIsAuthority;
/** Sync should be run in lieu of other syncs. */
private final boolean mIsExpedited;
+ /** Sync sound be ran as an expedited job. */
+ private final boolean mIsScheduledAsExpeditedJob;
/**
* {@hide}
@@ -79,6 +82,14 @@
/**
* {@hide}
+ * @return whether this sync is scheduled as an expedited job.
+ */
+ public boolean isScheduledAsExpeditedJob() {
+ return mIsScheduledAsExpeditedJob;
+ }
+
+ /**
+ * {@hide}
*
* @return account object for this sync.
* @throws IllegalArgumentException if this function is called for a request that targets a
@@ -149,6 +160,7 @@
parcel.writeInt((mDisallowMetered ? 1 : 0));
parcel.writeInt((mIsAuthority ? 1 : 0));
parcel.writeInt((mIsExpedited? 1 : 0));
+ parcel.writeInt(mIsScheduledAsExpeditedJob ? 1 : 0);
parcel.writeParcelable(mAccountToSync, flags);
parcel.writeString(mAuthority);
}
@@ -161,6 +173,7 @@
mDisallowMetered = (in.readInt() != 0);
mIsAuthority = (in.readInt() != 0);
mIsExpedited = (in.readInt() != 0);
+ mIsScheduledAsExpeditedJob = (in.readInt() != 0);
mAccountToSync = in.readParcelable(null);
mAuthority = in.readString();
}
@@ -174,6 +187,7 @@
mIsPeriodic = (b.mSyncType == Builder.SYNC_TYPE_PERIODIC);
mIsAuthority = (b.mSyncTarget == Builder.SYNC_TARGET_ADAPTER);
mIsExpedited = b.mExpedited;
+ mIsScheduledAsExpeditedJob = b.mScheduleAsExpeditedJob;
mExtras = new Bundle(b.mCustomExtras);
// For now we merge the sync config extras & the custom extras into one bundle.
// TODO: pass the configuration extras through separately.
@@ -258,6 +272,11 @@
*/
private boolean mRequiresCharging;
+ /**
+ * Whether the sync should be scheduled as an expedited job.
+ */
+ private boolean mScheduleAsExpeditedJob;
+
public Builder() {
}
@@ -309,7 +328,8 @@
* {@link ContentResolver#SYNC_EXTRAS_INITIALIZE},
* {@link ContentResolver#SYNC_EXTRAS_FORCE},
* {@link ContentResolver#SYNC_EXTRAS_EXPEDITED},
- * {@link ContentResolver#SYNC_EXTRAS_MANUAL}
+ * {@link ContentResolver#SYNC_EXTRAS_MANUAL},
+ * {@link ContentResolver#SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB}
* set to true. If any are supplied then an <code>IllegalArgumentException</code> will
* be thrown.
*
@@ -500,6 +520,22 @@
}
/**
+ * Convenience function for setting
+ * {@link ContentResolver#SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB}.
+ *
+ * <p> Not to be confused with {@link ContentResolver#SYNC_EXTRAS_EXPEDITED}.
+ *
+ * <p> Not valid for periodic syncs, expedited syncs, and syncs that require charging - an
+ * <code>IllegalArgumentException</code> will be thrown in {@link #build()}.
+ *
+ * @param scheduleAsExpeditedJob whether to schedule as an expedited job. Default false.
+ */
+ public @NonNull Builder setScheduleAsExpeditedJob(boolean scheduleAsExpeditedJob) {
+ mScheduleAsExpeditedJob = scheduleAsExpeditedJob;
+ return this;
+ }
+
+ /**
* Performs validation over the request and throws the runtime exception
* <code>IllegalArgumentException</code> if this validation fails.
*
@@ -507,11 +543,6 @@
* builder.
*/
public SyncRequest build() {
- // Validate the extras bundle
- ContentResolver.validateSyncExtrasBundle(mCustomExtras);
- if (mCustomExtras == null) {
- mCustomExtras = new Bundle();
- }
// Combine builder extra flags into the config bundle.
mSyncConfigExtras = new Bundle();
if (mIgnoreBackoff) {
@@ -532,17 +563,35 @@
if (mExpedited) {
mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
}
+ if (mScheduleAsExpeditedJob) {
+ mSyncConfigExtras.putBoolean(
+ ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, true);
+ }
if (mIsManual) {
mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true);
mSyncConfigExtras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
}
+
+ if (mCustomExtras == null) {
+ mCustomExtras = new Bundle();
+ }
+ // Validate the extras bundles
+ ContentResolver.validateSyncExtrasBundle(mCustomExtras);
+ // If this is a periodic sync ensure than invalid extras were not set.
if (mSyncType == SYNC_TYPE_PERIODIC) {
- // If this is a periodic sync ensure than invalid extras were not set.
if (ContentResolver.invalidPeriodicExtras(mCustomExtras) ||
ContentResolver.invalidPeriodicExtras(mSyncConfigExtras)) {
throw new IllegalArgumentException("Illegal extras were set");
}
}
+ // If this sync is scheduled as an EJ, ensure that invalid extras were not set.
+ if (mCustomExtras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB)
+ || mScheduleAsExpeditedJob) {
+ if (ContentResolver.hasInvalidScheduleAsEjExtras(mCustomExtras)
+ || ContentResolver.hasInvalidScheduleAsEjExtras(mSyncConfigExtras)) {
+ throw new IllegalArgumentException("Illegal extras were set");
+ }
+ }
// Ensure that a target for the sync has been set.
if (mSyncTarget == SYNC_TARGET_UNKNOWN) {
throw new IllegalArgumentException("Must specify an adapter with" +
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index dec2c3d..0aa1be9 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -136,6 +136,18 @@
public int fullBackupContent = 0;
/**
+ * Applications can set this attribute to an xml resource within their app where they specified
+ * the rules determining which files and directories can be copied from the device as part of
+ * backup or transfer operations.
+ *<p>
+ * Set from the {@link android.R.styleable#AndroidManifestApplication_dataExtractionRules}
+ * attribute in the manifest.
+ *
+ * @hide
+ */
+ public int dataExtractionRulesRes = 0;
+
+ /**
* <code>true</code> if the package is capable of presenting a unified interface representing
* multiple profiles.
* @hide
@@ -1520,6 +1532,9 @@
pw.println(prefix + "fullBackupContent="
+ (fullBackupContent < 0 ? "false" : "true"));
}
+ if (dataExtractionRulesRes != 0) {
+ pw.println(prefix + "dataExtractionRules=@xml/" + dataExtractionRulesRes);
+ }
pw.println(prefix + "crossProfile=" + (crossProfile ? "true" : "false"));
if (networkSecurityConfigRes != 0) {
pw.println(prefix + "networkSecurityConfigRes=0x"
@@ -1749,6 +1764,7 @@
uiOptions = orig.uiOptions;
backupAgentName = orig.backupAgentName;
fullBackupContent = orig.fullBackupContent;
+ dataExtractionRulesRes = orig.dataExtractionRulesRes;
crossProfile = orig.crossProfile;
networkSecurityConfigRes = orig.networkSecurityConfigRes;
category = orig.category;
@@ -1836,6 +1852,7 @@
dest.writeInt(descriptionRes);
dest.writeInt(uiOptions);
dest.writeInt(fullBackupContent);
+ dest.writeInt(dataExtractionRulesRes);
dest.writeBoolean(crossProfile);
dest.writeInt(networkSecurityConfigRes);
dest.writeInt(category);
@@ -1920,6 +1937,7 @@
descriptionRes = source.readInt();
uiOptions = source.readInt();
fullBackupContent = source.readInt();
+ dataExtractionRulesRes = source.readInt();
crossProfile = source.readBoolean();
networkSecurityConfigRes = source.readInt();
category = source.readInt();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f9122b1..ca88241 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3601,7 +3601,7 @@
* 1 - IncFs v1, core features, no PerUid support. Optional in R.
* 2 - IncFs v2, PerUid support, fs-verity support. Required in S.
*
- * @see IncrementalManager#isFeatureEnabled and IncrementalManager#isV2()
+ * @see IncrementalManager#getVersion()
* @hide
*/
@SystemApi
@@ -3623,11 +3623,26 @@
/**
* 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,
+ * microphone. When sensory privacy for the microphone is enabled no microphone data is sent to
+ * clients, e.g. all audio data is silent.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_MICROPHONE_TOGGLE = "android.hardware.microphone.toggle";
+
+ /**
+ * 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 sent to clients,
* e.g. the view finder in a camera app would appear blank.
*
* @hide
*/
+ @SystemApi
+ @TestApi
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CAMERA_TOGGLE = "android.hardware.camera.toggle";
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 7a01392..29edd40 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -260,6 +260,8 @@
ParsingPackage setFullBackupContent(int fullBackupContent);
+ ParsingPackage setDataExtractionRules(int dataExtractionRules);
+
ParsingPackage setHasDomainUrls(boolean hasDomainUrls);
ParsingPackage setIconRes(int iconRes);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index c1a93d8..067787d 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -334,6 +334,7 @@
private int descriptionRes;
private int fullBackupContent;
+ private int dataExtractionRules;
private int iconRes;
private int installLocation = ParsingPackageUtils.PARSE_DEFAULT_INSTALL_LOCATION;
private int labelRes;
@@ -1015,6 +1016,7 @@
appInfo.enabled = getBoolean(Booleans.ENABLED);
// appInfo.enabledSetting
appInfo.fullBackupContent = fullBackupContent;
+ appInfo.dataExtractionRulesRes = dataExtractionRules;
// TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy
// appInfo.mHiddenApiPolicy
// appInfo.hiddenUntilInstalled
@@ -1163,6 +1165,7 @@
dest.writeInt(this.compatibleWidthLimitDp);
dest.writeInt(this.descriptionRes);
dest.writeInt(this.fullBackupContent);
+ dest.writeInt(this.dataExtractionRules);
dest.writeInt(this.iconRes);
dest.writeInt(this.installLocation);
dest.writeInt(this.labelRes);
@@ -1284,6 +1287,7 @@
this.compatibleWidthLimitDp = in.readInt();
this.descriptionRes = in.readInt();
this.fullBackupContent = in.readInt();
+ this.dataExtractionRules = in.readInt();
this.iconRes = in.readInt();
this.installLocation = in.readInt();
this.labelRes = in.readInt();
@@ -1808,6 +1812,11 @@
}
@Override
+ public int getDataExtractionRules() {
+ return dataExtractionRules;
+ }
+
+ @Override
public int getIconRes() {
return iconRes;
}
@@ -2264,6 +2273,12 @@
}
@Override
+ public ParsingPackageImpl setDataExtractionRules(int value) {
+ dataExtractionRules = value;
+ return this;
+ }
+
+ @Override
public ParsingPackageImpl setIconRes(int value) {
iconRes = value;
return this;
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index ff4cebd..f7f3e19 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -587,6 +587,11 @@
*/
int getFullBackupContent();
+ /**
+ * @see R.styleable#AndroidManifestApplication_dataExtractionRules
+ */
+ int getDataExtractionRules();
+
/** @see ApplicationInfo#PRIVATE_FLAG_HAS_DOMAIN_URLS */
boolean isHasDomainUrls();
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index b7aa30f..0c033fd 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -2168,6 +2168,8 @@
.setNetworkSecurityConfigRes(resId(R.styleable.AndroidManifestApplication_networkSecurityConfig, sa))
.setRoundIconRes(resId(R.styleable.AndroidManifestApplication_roundIcon, sa))
.setTheme(resId(R.styleable.AndroidManifestApplication_theme, sa))
+ .setDataExtractionRules(
+ resId(R.styleable.AndroidManifestApplication_dataExtractionRules, sa))
// Strings
.setClassLoaderName(string(R.styleable.AndroidManifestApplication_classLoader, sa))
.setRequiredAccountType(string(R.styleable.AndroidManifestApplication_requiredAccountType, sa))
diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java
index f4f9e17..e03c1f4 100644
--- a/core/java/android/hardware/SensorPrivacyManager.java
+++ b/core/java/android/hardware/SensorPrivacyManager.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
@@ -33,6 +34,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
/**
* This class provides access to the sensor privacy services; sensor privacy allows the
@@ -42,9 +44,21 @@
*
* @hide
*/
+@SystemApi
@TestApi
@SystemService(Context.SENSOR_PRIVACY_SERVICE)
public final class SensorPrivacyManager {
+
+ /**
+ * @hide
+ */
+ public static final boolean USE_MICROPHONE_TOGGLE = true;
+
+ /**
+ * @hide
+ */
+ public static final boolean USE_CAMERA_TOGGLE = true;
+
/**
* Unique Id of this manager to identify to the service
* @hide
@@ -58,28 +72,39 @@
public static final String EXTRA_SENSOR = SensorPrivacyManager.class.getName()
+ ".extra.sensor";
- /** Microphone
- * @hide */
- @TestApi
- public static final int INDIVIDUAL_SENSOR_MICROPHONE =
- SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
-
- /** Camera
- * @hide */
- @TestApi
- public static final int INDIVIDUAL_SENSOR_CAMERA =
- SensorPrivacyIndividualEnabledSensorProto.CAMERA;
-
/**
- * Individual sensors not listed in {@link Sensor}
+ * Individual sensors not listed in {@link Sensors}
* @hide
*/
- @IntDef(prefix = "INDIVIDUAL_SENSOR_", value = {
- INDIVIDUAL_SENSOR_MICROPHONE,
- INDIVIDUAL_SENSOR_CAMERA
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface IndividualSensor {}
+ @SystemApi
+ @TestApi
+ public static class Sensors {
+
+ private Sensors() {}
+
+ /** Microphone
+ * @hide */
+ @SystemApi
+ @TestApi
+ public static final int MICROPHONE = SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+ /** Camera
+ * @hide */
+ @SystemApi
+ @TestApi
+ public static final int CAMERA = SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+
+ /**
+ * Individual sensors not listed in {@link Sensors}
+ *
+ * @hide
+ */
+ @IntDef(value = {
+ MICROPHONE,
+ CAMERA
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Sensor {}
+ }
/**
* A class implementing this interface can register with the {@link
@@ -88,6 +113,8 @@
*
* @hide
*/
+ @SystemApi
+ @TestApi
public interface OnSensorPrivacyChangedListener {
/**
* Callback invoked when the sensor privacy state changes.
@@ -165,7 +192,8 @@
*
* @hide
*/
- public void addSensorPrivacyListener(final OnSensorPrivacyChangedListener listener) {
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+ public void addSensorPrivacyListener(@NonNull final OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) {
ISensorPrivacyListener iListener = mListeners.get(listener);
if (iListener == null) {
@@ -196,15 +224,37 @@
*
* @hide
*/
- public void addSensorPrivacyListener(@IndividualSensor int sensor,
- final OnSensorPrivacyChangedListener listener) {
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+ public void addSensorPrivacyListener(@Sensors.Sensor int sensor,
+ @NonNull OnSensorPrivacyChangedListener listener) {
+ addSensorPrivacyListener(sensor, mContext.getMainExecutor(), listener);
+ }
+
+ /**
+ * Registers a new listener to receive notification when the state of sensor privacy
+ * changes.
+ *
+ * @param sensor the sensor to listen to changes to
+ * @param executor the executor to dispatch the callback on
+ * @param listener the OnSensorPrivacyChangedListener to be notified when the state of sensor
+ * privacy changes.
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+ public void addSensorPrivacyListener(@Sensors.Sensor int sensor, @NonNull Executor executor,
+ @NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) {
ISensorPrivacyListener iListener = mListeners.get(listener);
if (iListener == null) {
iListener = new ISensorPrivacyListener.Stub() {
@Override
public void onSensorPrivacyChanged(boolean enabled) {
- listener.onSensorPrivacyChanged(enabled);
+ executor.execute(() -> listener.onSensorPrivacyChanged(enabled));
}
};
mListeners.put(listener, iListener);
@@ -228,7 +278,10 @@
*
* @hide
*/
- public void removeSensorPrivacyListener(OnSensorPrivacyChangedListener listener) {
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+ public void removeSensorPrivacyListener(@NonNull OnSensorPrivacyChangedListener listener) {
synchronized (mListeners) {
ISensorPrivacyListener iListener = mListeners.get(listener);
if (iListener != null) {
@@ -249,6 +302,7 @@
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
public boolean isSensorPrivacyEnabled() {
try {
return mService.isSensorPrivacyEnabled();
@@ -264,8 +318,10 @@
*
* @hide
*/
+ @SystemApi
@TestApi
- public boolean isIndividualSensorPrivacyEnabled(@IndividualSensor int sensor) {
+ @RequiresPermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY)
+ public boolean isSensorPrivacyEnabled(@Sensors.Sensor int sensor) {
try {
return mService.isIndividualSensorPrivacyEnabled(mContext.getUserId(), sensor);
} catch (RemoteException e) {
@@ -283,8 +339,7 @@
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
- public void setIndividualSensorPrivacy(@IndividualSensor int sensor,
- boolean enable) {
+ public void setSensorPrivacy(@Sensors.Sensor int sensor, boolean enable) {
try {
mService.setIndividualSensorPrivacy(mContext.getUserId(), sensor, enable);
} catch (RemoteException e) {
@@ -303,7 +358,7 @@
*/
@TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
- public void setIndividualSensorPrivacyForProfileGroup(@IndividualSensor int sensor,
+ public void setSensorPrivacyForProfileGroup(@Sensors.Sensor int sensor,
boolean enable) {
try {
mService.setIndividualSensorPrivacyForProfileGroup(mContext.getUserId(), sensor,
@@ -321,7 +376,8 @@
*
* @hide
*/
- public void suppressIndividualSensorPrivacyReminders(@NonNull String packageName,
+ @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY)
+ public void suppressSensorPrivacyReminders(@NonNull String packageName,
boolean suppress) {
try {
mService.suppressIndividualSensorPrivacyReminders(mContext.getUserId(), packageName,
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 76d50bd..43ef33e 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -145,6 +145,12 @@
int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
/**
+ * Authentication cannot proceed because re-enrollment is required.
+ * @hide
+ */
+ int BIOMETRIC_ERROR_RE_ENROLL = 16;
+
+ /**
* This constant is only used by SystemUI. It notifies SystemUI that authentication was paused
* because the authentication attempt was unsuccessful.
* @hide
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index eafcf52..4385b1da 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -153,6 +153,12 @@
int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
/**
+ * Authentication cannot proceed because re-enrollment is required.
+ * @hide
+ */
+ int BIOMETRIC_ERROR_RE_ENROLL = 16;
+
+ /**
* @hide
*/
int FACE_ERROR_VENDOR_BASE = 1000;
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index 01f0e71..30e24d2e 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -166,6 +166,12 @@
public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
/**
+ * Authentication cannot proceed because re-enrollment is required.
+ * @hide
+ */
+ int BIOMETRIC_ERROR_RE_ENROLL = 16;
+
+ /**
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/core/java/android/hardware/display/DeviceProductInfo.java b/core/java/android/hardware/display/DeviceProductInfo.java
index 9457d8f1..41126b7 100644
--- a/core/java/android/hardware/display/DeviceProductInfo.java
+++ b/core/java/android/hardware/display/DeviceProductInfo.java
@@ -16,69 +16,40 @@
package android.hardware.display;
-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.Arrays;
import java.util.Objects;
/**
* Product-specific information about the display or the directly connected device on the
* display chain. For example, if the display is transitively connected, this field may contain
* product information about the intermediate device.
+ * @hide
*/
public final class DeviceProductInfo implements Parcelable {
- /** @hide */
- @IntDef(prefix = {"CONNECTION_TO_SINK_"}, value = {
- CONNECTION_TO_SINK_UNKNOWN,
- CONNECTION_TO_SINK_BUILT_IN,
- CONNECTION_TO_SINK_DIRECT,
- CONNECTION_TO_SINK_TRANSITIVE
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface ConnectionToSinkType { }
-
- /** The device connection to the display sink is unknown. */
- public static final int CONNECTION_TO_SINK_UNKNOWN =
- IDeviceProductInfoConstants.CONNECTION_TO_SINK_UNKNOWN;
-
- /** The display sink is built-in to the device */
- public static final int CONNECTION_TO_SINK_BUILT_IN =
- IDeviceProductInfoConstants.CONNECTION_TO_SINK_BUILT_IN;
-
- /** The device is directly connected to the display sink. */
- public static final int CONNECTION_TO_SINK_DIRECT =
- IDeviceProductInfoConstants.CONNECTION_TO_SINK_DIRECT;
-
- /** The device is transitively connected to the display sink. */
- public static final int CONNECTION_TO_SINK_TRANSITIVE =
- IDeviceProductInfoConstants.CONNECTION_TO_SINK_TRANSITIVE;
-
private final String mName;
private final String mManufacturerPnpId;
private final String mProductId;
private final Integer mModelYear;
private final ManufactureDate mManufactureDate;
- private final @ConnectionToSinkType int mConnectionToSinkType;
+ private final int[] mRelativeAddress;
- /** @hide */
public DeviceProductInfo(
String name,
String manufacturerPnpId,
String productId,
Integer modelYear,
ManufactureDate manufactureDate,
- int connectionToSinkType) {
+ int[] relativeAddress) {
this.mName = name;
this.mManufacturerPnpId = manufacturerPnpId;
this.mProductId = productId;
this.mModelYear = modelYear;
this.mManufactureDate = manufactureDate;
- this.mConnectionToSinkType = connectionToSinkType;
+ this.mRelativeAddress = relativeAddress;
}
private DeviceProductInfo(Parcel in) {
@@ -87,13 +58,12 @@
mProductId = (String) in.readValue(null);
mModelYear = (Integer) in.readValue(null);
mManufactureDate = (ManufactureDate) in.readValue(null);
- mConnectionToSinkType = in.readInt();
+ mRelativeAddress = in.createIntArray();
}
/**
* @return Display name.
*/
- @Nullable
public String getName() {
return mName;
}
@@ -101,7 +71,6 @@
/**
* @return Manufacturer Plug and Play ID.
*/
- @NonNull
public String getManufacturerPnpId() {
return mManufacturerPnpId;
}
@@ -109,58 +78,32 @@
/**
* @return Manufacturer product ID.
*/
- @NonNull
public String getProductId() {
return mProductId;
}
/**
- * @return Model year of the device. Return -1 if not available. Typically,
- * one of model year or manufacture year is available.
+ * @return Model year of the device. Typically exactly one of model year or
+ * manufacture date will be present.
*/
- public int getModelYear() {
- return mModelYear != null ? mModelYear : -1;
- }
-
- /**
- * @return The year of manufacture, or -1 it is not available. Typically,
- * one of model year or manufacture year is available.
- */
- public int getManufactureYear() {
- if (mManufactureDate == null) {
- return -1;
- }
- return mManufactureDate.mYear != null ? mManufactureDate.mYear : -1;
- }
-
- /**
- * @return The week of manufacture, or -1 it is not available. Typically,
- * not present if model year is available.
- */
- public int getManufactureWeek() {
- if (mManufactureDate == null) {
- return -1;
- }
- return mManufactureDate.mWeek != null ? mManufactureDate.mWeek : -1;
+ public Integer getModelYear() {
+ return mModelYear;
}
/**
* @return Manufacture date. Typically exactly one of model year or manufacture
* date will be present.
- *
- * @hide
*/
public ManufactureDate getManufactureDate() {
return mManufactureDate;
}
/**
- * @return How the current device is connected to the display sink. For example, the display
- * can be connected immediately to the device or there can be a receiver in between.
+ * @return Relative address in the display network. For example, for HDMI connected devices this
+ * can be its physical address. Each component of the address is in the range [0, 255].
*/
- @ConnectionToSinkType
- public int getConnectionToSinkType() {
- return mConnectionToSinkType;
+ public int[] getRelativeAddress() {
+ return mRelativeAddress;
}
@Override
@@ -176,8 +119,8 @@
+ mModelYear
+ ", manufactureDate="
+ mManufactureDate
- + ", connectionToSinkType="
- + mConnectionToSinkType
+ + ", relativeAddress="
+ + Arrays.toString(mRelativeAddress)
+ '}';
}
@@ -191,16 +134,16 @@
&& Objects.equals(mProductId, that.mProductId)
&& Objects.equals(mModelYear, that.mModelYear)
&& Objects.equals(mManufactureDate, that.mManufactureDate)
- && mConnectionToSinkType == that.mConnectionToSinkType;
+ && Arrays.equals(mRelativeAddress, that.mRelativeAddress);
}
@Override
public int hashCode() {
return Objects.hash(mName, mManufacturerPnpId, mProductId, mModelYear, mManufactureDate,
- mConnectionToSinkType);
+ Arrays.hashCode(mRelativeAddress));
}
- @NonNull public static final Creator<DeviceProductInfo> CREATOR =
+ public static final Creator<DeviceProductInfo> CREATOR =
new Creator<DeviceProductInfo>() {
@Override
public DeviceProductInfo createFromParcel(Parcel in) {
@@ -219,13 +162,13 @@
}
@Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
+ public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mName);
dest.writeString(mManufacturerPnpId);
dest.writeValue(mProductId);
dest.writeValue(mModelYear);
dest.writeValue(mManufactureDate);
- dest.writeInt(mConnectionToSinkType);
+ dest.writeIntArray(mRelativeAddress);
}
/**
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index a9bcdeff..f868a50 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -831,6 +831,9 @@
case BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED:
return context.getString(
com.android.internal.R.string.face_error_security_update_required);
+ case BIOMETRIC_ERROR_RE_ENROLL:
+ return context.getString(
+ com.android.internal.R.string.face_recalibrate_notification_content);
case FACE_ERROR_VENDOR: {
String[] msgArray = context.getResources().getStringArray(
com.android.internal.R.array.face_error_vendor);
@@ -1389,7 +1392,7 @@
case FACE_ACQUIRED_PAN_TOO_EXTREME:
case FACE_ACQUIRED_TILT_TOO_EXTREME:
case FACE_ACQUIRED_ROLL_TOO_EXTREME:
- return context.getString(R.string.face_acquired_not_detected);
+ return context.getString(R.string.face_acquired_poor_gaze);
// Provide more detailed feedback for other soft errors.
case FACE_ACQUIRED_INSUFFICIENT:
diff --git a/core/java/android/hardware/input/OWNERS b/core/java/android/hardware/input/OWNERS
index 25e02e1..c390b33 100644
--- a/core/java/android/hardware/input/OWNERS
+++ b/core/java/android/hardware/input/OWNERS
@@ -1,6 +1,3 @@
# Bug component: 136048
include /services/core/java/com/android/server/input/OWNERS
-
-michaelwr@google.com
-svv@google.com
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index 79f9e6e..dbb3127 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -15,9 +15,6 @@
*/
package android.net;
-import static android.Manifest.permission.NETWORK_STACK;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -26,8 +23,7 @@
import android.os.IBinder;
import android.os.ServiceManager;
-import java.util.ArrayList;
-import java.util.Arrays;
+import com.android.net.module.util.PermissionUtils;
/**
* Constants and utilities for client code communicating with the network stack service.
* @hide
@@ -79,9 +75,14 @@
* @param context {@link android.content.Context} for the process.
*
* @hide
+ *
+ * @deprecated Use {@link PermissionUtils#enforceNetworkStackPermission} instead.
+ *
+ * TODO: remove this method and let the users call to PermissionUtils directly.
*/
+ @Deprecated
public static void checkNetworkStackPermission(final @NonNull Context context) {
- checkNetworkStackPermissionOr(context);
+ PermissionUtils.enforceNetworkStackPermission(context);
}
/**
@@ -92,31 +93,14 @@
* @param otherPermissions The set of permissions that could be the candidate permissions , or
* empty string if none of other permissions needed.
* @hide
+ *
+ * @deprecated Use {@link PermissionUtils#enforceNetworkStackPermissionOr} instead.
+ *
+ * TODO: remove this method and let the users call to PermissionUtils directly.
*/
+ @Deprecated
public static void checkNetworkStackPermissionOr(final @NonNull Context context,
final @NonNull String... otherPermissions) {
- ArrayList<String> permissions = new ArrayList<String>(Arrays.asList(otherPermissions));
- permissions.add(NETWORK_STACK);
- permissions.add(PERMISSION_MAINLINE_NETWORK_STACK);
- enforceAnyPermissionOf(context, permissions.toArray(new String[0]));
+ PermissionUtils.enforceNetworkStackPermissionOr(context, otherPermissions);
}
-
- private static void enforceAnyPermissionOf(final @NonNull Context context,
- final @NonNull String... permissions) {
- if (!checkAnyPermissionOf(context, permissions)) {
- throw new SecurityException("Requires one of the following permissions: "
- + String.join(", ", permissions) + ".");
- }
- }
-
- private static boolean checkAnyPermissionOf(final @NonNull Context context,
- final @NonNull String... permissions) {
- for (String permission : permissions) {
- if (context.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
- return true;
- }
- }
- return false;
- }
-
}
diff --git a/core/java/android/net/UidRange.java b/core/java/android/net/UidRange.java
index b172ccc..f0e7da7 100644
--- a/core/java/android/net/UidRange.java
+++ b/core/java/android/net/UidRange.java
@@ -42,10 +42,6 @@
stop = stopUid;
}
- public static UidRange createForUser(int userId) {
- return new UidRange(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
- }
-
/** Creates a UidRange for the specified user. */
public static UidRange createForUser(UserHandle user) {
final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1);
diff --git a/core/java/android/net/vcn/IVcnStatusCallback.aidl b/core/java/android/net/vcn/IVcnStatusCallback.aidl
index 555e9b5..d91cef5 100644
--- a/core/java/android/net/vcn/IVcnStatusCallback.aidl
+++ b/core/java/android/net/vcn/IVcnStatusCallback.aidl
@@ -17,8 +17,9 @@
package android.net.vcn;
/** @hide */
-interface IVcnStatusCallback {
+oneway interface IVcnStatusCallback {
void onEnteredSafeMode();
+ void onVcnStatusChanged(int statusCode);
void onGatewayConnectionError(
in int[] gatewayNetworkCapabilities,
int errorCode,
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index aea0ea9..eb8c251 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.net.LinkProperties;
@@ -72,8 +73,7 @@
public class VcnManager {
@NonNull private static final String TAG = VcnManager.class.getSimpleName();
- private static final Map<
- VcnUnderlyingNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
+ private static final Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();
@NonNull private final Context mContext;
@@ -93,13 +93,13 @@
}
/**
- * Get all currently registered VcnUnderlyingNetworkPolicyListeners for testing purposes.
+ * Get all currently registered VcnNetworkPolicyListeners for testing purposes.
*
* @hide
*/
@VisibleForTesting(visibility = Visibility.PRIVATE)
@NonNull
- public static Map<VcnUnderlyingNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
+ public static Map<VcnNetworkPolicyListener, VcnUnderlyingNetworkPolicyListenerBinder>
getAllPolicyListeners() {
return Collections.unmodifiableMap(REGISTERED_POLICY_LISTENERS);
}
@@ -161,22 +161,15 @@
}
}
- // TODO: make VcnUnderlyingNetworkPolicyListener @SystemApi
+ // TODO(b/180537630): remove all VcnUnderlyingNetworkPolicyListener refs once Telephony is using
+ // the new VcnNetworkPolicyListener API
/**
* VcnUnderlyingNetworkPolicyListener is the interface through which internal system components
* can register to receive updates for VCN-underlying Network policies from the System Server.
*
* @hide
*/
- public interface VcnUnderlyingNetworkPolicyListener {
- /**
- * Notifies the implementation that the VCN's underlying Network policy has changed.
- *
- * <p>After receiving this callback, implementations MUST poll VcnManager for the updated
- * VcnUnderlyingNetworkPolicy via VcnManager#getUnderlyingNetworkPolicy.
- */
- void onPolicyChanged();
- }
+ public interface VcnUnderlyingNetworkPolicyListener extends VcnNetworkPolicyListener {}
/**
* Add a listener for VCN-underlying network policy updates.
@@ -185,29 +178,14 @@
* Listener
* @param listener the VcnUnderlyingNetworkPolicyListener to be added
* @throws SecurityException if the caller does not have permission NETWORK_FACTORY
- * @throws IllegalArgumentException if the specified VcnUnderlyingNetworkPolicyListener is
- * already registered
+ * @throws IllegalStateException if the specified VcnUnderlyingNetworkPolicyListener is already
+ * registered
* @hide
*/
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public void addVcnUnderlyingNetworkPolicyListener(
@NonNull Executor executor, @NonNull VcnUnderlyingNetworkPolicyListener listener) {
- requireNonNull(executor, "executor must not be null");
- requireNonNull(listener, "listener must not be null");
-
- VcnUnderlyingNetworkPolicyListenerBinder binder =
- new VcnUnderlyingNetworkPolicyListenerBinder(executor, listener);
- if (REGISTERED_POLICY_LISTENERS.putIfAbsent(listener, binder) != null) {
- throw new IllegalArgumentException(
- "Attempting to add a listener that is already in use");
- }
-
- try {
- mService.addVcnUnderlyingNetworkPolicyListener(binder);
- } catch (RemoteException e) {
- REGISTERED_POLICY_LISTENERS.remove(listener);
- throw e.rethrowFromSystemServer();
- }
+ addVcnNetworkPolicyListener(executor, listener);
}
/**
@@ -220,19 +198,7 @@
*/
public void removeVcnUnderlyingNetworkPolicyListener(
@NonNull VcnUnderlyingNetworkPolicyListener listener) {
- requireNonNull(listener, "listener must not be null");
-
- VcnUnderlyingNetworkPolicyListenerBinder binder =
- REGISTERED_POLICY_LISTENERS.remove(listener);
- if (binder == null) {
- return;
- }
-
- try {
- mService.removeVcnUnderlyingNetworkPolicyListener(binder);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ removeVcnNetworkPolicyListener(listener);
}
/**
@@ -266,6 +232,170 @@
}
}
+ /**
+ * VcnNetworkPolicyListener is the interface through which internal system components (e.g.
+ * Network Factories) can register to receive updates for VCN-underlying Network policies from
+ * the System Server.
+ *
+ * <p>Any Network Factory that brings up Networks capable of being VCN-underlying Networks
+ * should register a VcnNetworkPolicyListener. VcnManager will then use this listener to notify
+ * the registrant when VCN Network policies change. Upon receiving this signal, the listener
+ * must check {@link VcnManager} for the current Network policy result for each of its Networks
+ * via {@link #applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface VcnNetworkPolicyListener {
+ /**
+ * Notifies the implementation that the VCN's underlying Network policy has changed.
+ *
+ * <p>After receiving this callback, implementations should get the current {@link
+ * VcnNetworkPolicyResult} via {@link #applyVcnNetworkPolicy(NetworkCapabilities,
+ * LinkProperties)}.
+ */
+ void onPolicyChanged();
+ }
+
+ /**
+ * Add a listener for VCN-underlying Network policy updates.
+ *
+ * <p>A {@link VcnNetworkPolicyListener} is eligible to begin receiving callbacks once it is
+ * registered. No callbacks are guaranteed upon registration.
+ *
+ * @param executor the Executor that will be used for invoking all calls to the specified
+ * Listener
+ * @param listener the VcnNetworkPolicyListener to be added
+ * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
+ * @throws IllegalStateException if the specified VcnNetworkPolicyListener is already registered
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public void addVcnNetworkPolicyListener(
+ @NonNull Executor executor, @NonNull VcnNetworkPolicyListener listener) {
+ requireNonNull(executor, "executor must not be null");
+ requireNonNull(listener, "listener must not be null");
+
+ VcnUnderlyingNetworkPolicyListenerBinder binder =
+ new VcnUnderlyingNetworkPolicyListenerBinder(executor, listener);
+ if (REGISTERED_POLICY_LISTENERS.putIfAbsent(listener, binder) != null) {
+ throw new IllegalStateException("listener is already registered with VcnManager");
+ }
+
+ try {
+ mService.addVcnUnderlyingNetworkPolicyListener(binder);
+ } catch (RemoteException e) {
+ REGISTERED_POLICY_LISTENERS.remove(listener);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Remove the specified VcnNetworkPolicyListener from VcnManager.
+ *
+ * <p>If the specified listener is not currently registered, this is a no-op.
+ *
+ * @param listener the VcnNetworkPolicyListener that will be removed
+ * @hide
+ */
+ @SystemApi
+ public void removeVcnNetworkPolicyListener(@NonNull VcnNetworkPolicyListener listener) {
+ requireNonNull(listener, "listener must not be null");
+
+ VcnUnderlyingNetworkPolicyListenerBinder binder =
+ REGISTERED_POLICY_LISTENERS.remove(listener);
+ if (binder == null) {
+ return;
+ }
+
+ try {
+ mService.removeVcnUnderlyingNetworkPolicyListener(binder);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Applies the network policy for a {@link android.net.Network} with the given parameters.
+ *
+ * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
+ * may have changed via {@link VcnNetworkPolicyListener#onPolicyChanged()}, a Network Provider
+ * MUST poll for the updated Network policy based on that Network's capabilities and properties.
+ *
+ * @param networkCapabilities the NetworkCapabilities to be used in determining the Network
+ * policy result for this Network.
+ * @param linkProperties the LinkProperties to be used in determining the Network policy result
+ * for this Network.
+ * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
+ * @return the {@link VcnNetworkPolicyResult} to be used for this Network.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+ public VcnNetworkPolicyResult applyVcnNetworkPolicy(
+ @NonNull NetworkCapabilities networkCapabilities,
+ @NonNull LinkProperties linkProperties) {
+ requireNonNull(networkCapabilities, "networkCapabilities must not be null");
+ requireNonNull(linkProperties, "linkProperties must not be null");
+
+ final VcnUnderlyingNetworkPolicy policy =
+ getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
+ return new VcnNetworkPolicyResult(
+ policy.isTeardownRequested(), policy.getMergedNetworkCapabilities());
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ VCN_STATUS_CODE_NOT_CONFIGURED,
+ VCN_STATUS_CODE_INACTIVE,
+ VCN_STATUS_CODE_ACTIVE,
+ VCN_STATUS_CODE_SAFE_MODE
+ })
+ public @interface VcnStatusCode {}
+
+ /**
+ * Value indicating that the VCN for the subscription group is not configured, or that the
+ * callback is not privileged for the subscription group.
+ *
+ * @hide
+ */
+ public static final int VCN_STATUS_CODE_NOT_CONFIGURED = 0;
+
+ /**
+ * Value indicating that the VCN for the subscription group is inactive.
+ *
+ * <p>A VCN is inactive if a {@link VcnConfig} is present for the subscription group, but the
+ * provisioning package is not privileged.
+ *
+ * @hide
+ */
+ public static final int VCN_STATUS_CODE_INACTIVE = 1;
+
+ /**
+ * Value indicating that the VCN for the subscription group is active.
+ *
+ * <p>A VCN is active if a {@link VcnConfig} is present for the subscription, the provisioning
+ * package is privileged, and the VCN is not in Safe Mode. In other words, a VCN is considered
+ * active while it is connecting, fully connected, and disconnecting.
+ *
+ * @hide
+ */
+ public static final int VCN_STATUS_CODE_ACTIVE = 2;
+
+ /**
+ * Value indicating that the VCN for the subscription group is in Safe Mode.
+ *
+ * <p>A VCN will be put into Safe Mode if any of the gateway connections were unable to
+ * establish a connection within a system-determined timeout (while underlying networks were
+ * available).
+ *
+ * @hide
+ */
+ public static final int VCN_STATUS_CODE_SAFE_MODE = 3;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef({
@@ -323,8 +453,18 @@
*
* <p>A VCN-configuring app may opt to exit safe mode by (re)setting the VCN configuration
* via {@link #setVcnConfig(ParcelUuid, VcnConfig)}.
+ *
+ * @hide
*/
- public abstract void onEnteredSafeMode();
+ public void onEnteredSafeMode() {}
+
+ /**
+ * Invoked when status of the VCN for this callback's subscription group changes.
+ *
+ * @param statusCode the code for the status change encountered by this {@link
+ * VcnStatusCallback}'s subscription group.
+ */
+ public abstract void onVcnStatusChanged(@VcnStatusCode int statusCode);
/**
* Invoked when a VCN Gateway Connection corresponding to this callback's subscription
@@ -356,6 +496,11 @@
* <p>A {@link VcnStatusCallback} will only be invoked if the registering package has carrier
* privileges for the specified subscription at the time of invocation.
*
+ * <p>{@link VcnStatusCallback#onVcnStatusChanged(int)} will be invoked on registration with the
+ * current status for the specified subscription group's VCN. If the registrant is not
+ * privileged for this subscription group, {@link #VCN_STATUS_CODE_NOT_CONFIGURED} will be
+ * returned.
+ *
* @param subscriptionGroup The subscription group to match for callbacks
* @param executor The {@link Executor} to be used for invoking callbacks
* @param callback The VcnStatusCallback to be registered
@@ -415,18 +560,17 @@
}
/**
- * Binder wrapper for added VcnUnderlyingNetworkPolicyListeners to receive signals from System
- * Server.
+ * Binder wrapper for added VcnNetworkPolicyListeners to receive signals from System Server.
*
* @hide
*/
private static class VcnUnderlyingNetworkPolicyListenerBinder
extends IVcnUnderlyingNetworkPolicyListener.Stub {
@NonNull private final Executor mExecutor;
- @NonNull private final VcnUnderlyingNetworkPolicyListener mListener;
+ @NonNull private final VcnNetworkPolicyListener mListener;
private VcnUnderlyingNetworkPolicyListenerBinder(
- Executor executor, VcnUnderlyingNetworkPolicyListener listener) {
+ Executor executor, VcnNetworkPolicyListener listener) {
mExecutor = executor;
mListener = listener;
}
@@ -460,6 +604,12 @@
() -> mExecutor.execute(() -> mCallback.onEnteredSafeMode()));
}
+ @Override
+ public void onVcnStatusChanged(@VcnStatusCode int statusCode) {
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> mCallback.onVcnStatusChanged(statusCode)));
+ }
+
// TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
@Override
public void onGatewayConnectionError(
diff --git a/core/java/android/net/vcn/VcnNetworkPolicyResult.aidl b/core/java/android/net/vcn/VcnNetworkPolicyResult.aidl
new file mode 100644
index 0000000..3f13abe
--- /dev/null
+++ b/core/java/android/net/vcn/VcnNetworkPolicyResult.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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;
+
+/** @hide */
+parcelable VcnNetworkPolicyResult;
diff --git a/core/java/android/net/vcn/VcnNetworkPolicyResult.java b/core/java/android/net/vcn/VcnNetworkPolicyResult.java
new file mode 100644
index 0000000..5e93820
--- /dev/null
+++ b/core/java/android/net/vcn/VcnNetworkPolicyResult.java
@@ -0,0 +1,114 @@
+/*
+ * 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.SystemApi;
+import android.net.NetworkCapabilities;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * VcnNetworkPolicyResult represents the Network policy result for a Network transport applying its
+ * VCN policy via {@link VcnManager#applyVcnNetworkPolicy(NetworkCapabilities, LinkProperties)}.
+ *
+ * <p>Bearers that are bringing up networks capable of acting as a VCN's underlying network should
+ * query for Network policy results upon any capability changes (e.g. changing of TRUSTED bit), and
+ * when prompted by VcnManagementService via {@link VcnManager.VcnNetworkPolicyListener}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class VcnNetworkPolicyResult implements Parcelable {
+ private final boolean mIsTearDownRequested;
+ private final NetworkCapabilities mNetworkCapabilities;
+
+ /**
+ * Constructs a VcnNetworkPolicyResult with the specified parameters.
+ *
+ * @hide
+ */
+ public VcnNetworkPolicyResult(
+ boolean isTearDownRequested, @NonNull NetworkCapabilities networkCapabilities) {
+ Objects.requireNonNull(networkCapabilities, "networkCapabilities must be non-null");
+
+ mIsTearDownRequested = isTearDownRequested;
+ mNetworkCapabilities = networkCapabilities;
+ }
+
+ /**
+ * Returns whether this VCN policy result requires that the underlying Network should be torn
+ * down.
+ *
+ * <p>Upon querying for the current Network policy result, the bearer must check this method,
+ * and MUST tear down the corresponding Network if it returns true.
+ */
+ public boolean isTeardownRequested() {
+ return mIsTearDownRequested;
+ }
+
+ /**
+ * Returns the NetworkCapabilities that the bearer should be using for the corresponding
+ * Network.
+ */
+ @NonNull
+ public NetworkCapabilities getNetworkCapabilities() {
+ return mNetworkCapabilities;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIsTearDownRequested, mNetworkCapabilities);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof VcnNetworkPolicyResult)) return false;
+ final VcnNetworkPolicyResult that = (VcnNetworkPolicyResult) o;
+
+ return mIsTearDownRequested == that.mIsTearDownRequested
+ && mNetworkCapabilities.equals(that.mNetworkCapabilities);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeBoolean(mIsTearDownRequested);
+ dest.writeParcelable(mNetworkCapabilities, flags);
+ }
+
+ /** Implement the Parcelable interface */
+ public static final @NonNull Creator<VcnNetworkPolicyResult> CREATOR =
+ new Creator<VcnNetworkPolicyResult>() {
+ public VcnNetworkPolicyResult createFromParcel(Parcel in) {
+ return new VcnNetworkPolicyResult(in.readBoolean(), in.readParcelable(null));
+ }
+
+ public VcnNetworkPolicyResult[] newArray(int size) {
+ return new VcnNetworkPolicyResult[size];
+ }
+ };
+}
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java b/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
index dd7c86d8..b47d564 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
@@ -33,8 +33,7 @@
* @hide
*/
public final class VcnUnderlyingNetworkPolicy implements Parcelable {
- private final boolean mIsTearDownRequested;
- private final NetworkCapabilities mMergedNetworkCapabilities;
+ private final VcnNetworkPolicyResult mVcnNetworkPolicyResult;
/**
* Constructs a VcnUnderlyingNetworkPolicy with the specified parameters.
@@ -46,8 +45,13 @@
Objects.requireNonNull(
mergedNetworkCapabilities, "mergedNetworkCapabilities must be nonnull");
- mIsTearDownRequested = isTearDownRequested;
- mMergedNetworkCapabilities = mergedNetworkCapabilities;
+ mVcnNetworkPolicyResult =
+ new VcnNetworkPolicyResult(isTearDownRequested, mergedNetworkCapabilities);
+ }
+
+ private VcnUnderlyingNetworkPolicy(@NonNull VcnNetworkPolicyResult vcnNetworkPolicyResult) {
+ this.mVcnNetworkPolicyResult =
+ Objects.requireNonNull(vcnNetworkPolicyResult, "vcnNetworkPolicyResult");
}
/**
@@ -55,7 +59,7 @@
* be torn down.
*/
public boolean isTeardownRequested() {
- return mIsTearDownRequested;
+ return mVcnNetworkPolicyResult.isTeardownRequested();
}
/**
@@ -64,12 +68,12 @@
*/
@NonNull
public NetworkCapabilities getMergedNetworkCapabilities() {
- return mMergedNetworkCapabilities;
+ return mVcnNetworkPolicyResult.getNetworkCapabilities();
}
@Override
public int hashCode() {
- return Objects.hash(mIsTearDownRequested, mMergedNetworkCapabilities);
+ return Objects.hash(mVcnNetworkPolicyResult);
}
@Override
@@ -78,8 +82,7 @@
if (!(o instanceof VcnUnderlyingNetworkPolicy)) return false;
final VcnUnderlyingNetworkPolicy that = (VcnUnderlyingNetworkPolicy) o;
- return mIsTearDownRequested == that.mIsTearDownRequested
- && mMergedNetworkCapabilities.equals(that.mMergedNetworkCapabilities);
+ return mVcnNetworkPolicyResult.equals(that.mVcnNetworkPolicyResult);
}
/** {@inheritDoc} */
@@ -91,16 +94,14 @@
/** {@inheritDoc} */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeBoolean(mIsTearDownRequested);
- dest.writeParcelable(mMergedNetworkCapabilities, flags);
+ dest.writeParcelable(mVcnNetworkPolicyResult, flags);
}
/** Implement the Parcelable interface */
public static final @NonNull Creator<VcnUnderlyingNetworkPolicy> CREATOR =
new Creator<VcnUnderlyingNetworkPolicy>() {
public VcnUnderlyingNetworkPolicy createFromParcel(Parcel in) {
- return new VcnUnderlyingNetworkPolicy(
- in.readBoolean(), in.readParcelable(null));
+ return new VcnUnderlyingNetworkPolicy(in.readParcelable(null));
}
public VcnUnderlyingNetworkPolicy[] newArray(int size) {
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index c6efaac..2b6f336 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -47,6 +47,7 @@
POWER_COMPONENT_SYSTEM_SERVICES,
POWER_COMPONENT_SENSORS,
POWER_COMPONENT_GNSS,
+ POWER_COMPONENT_WIFI,
POWER_COMPONENT_WAKELOCK,
POWER_COMPONENT_SCREEN,
POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS,
@@ -66,6 +67,7 @@
public static final int POWER_COMPONENT_MOBILE_RADIO = 8;
public static final int POWER_COMPONENT_SENSORS = 9;
public static final int POWER_COMPONENT_GNSS = 10;
+ public static final int POWER_COMPONENT_WIFI = 11;
public static final int POWER_COMPONENT_WAKELOCK = 12;
public static final int POWER_COMPONENT_SCREEN = 13;
// Power that is re-attributed to other battery consumers. For example, for System Server
@@ -94,6 +96,7 @@
TIME_COMPONENT_MOBILE_RADIO,
TIME_COMPONENT_SENSORS,
TIME_COMPONENT_GNSS,
+ TIME_COMPONENT_WIFI,
TIME_COMPONENT_WAKELOCK,
TIME_COMPONENT_SCREEN,
})
@@ -112,6 +115,7 @@
public static final int TIME_COMPONENT_MOBILE_RADIO = 8;
public static final int TIME_COMPONENT_SENSORS = 9;
public static final int TIME_COMPONENT_GNSS = 10;
+ public static final int TIME_COMPONENT_WIFI = 11;
public static final int TIME_COMPONENT_WAKELOCK = 12;
public static final int TIME_COMPONENT_SCREEN = 13;
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 305c686..a435ac1 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -25,6 +25,7 @@
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.WorkerThread;
import android.app.ActivityManager;
import android.content.Context;
import android.util.Log;
@@ -41,7 +42,15 @@
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
-/** Class that provides a privileged API to capture and consume bugreports. */
+/**
+ * Class that provides a privileged API to capture and consume bugreports.
+ *
+ * <p>This class may only be used by apps that currently have carrier privileges (see {@link
+ * android.telephony.TelephonyManager#hasCarrierPrivileges}) on an active SIM or priv-apps
+ * explicitly allowed by the device manufacturer.
+ *
+ * <p>Only one bugreport can be generated by the system at a time.
+ */
@SystemService(Context.BUGREPORT_SERVICE)
public final class BugreportManager {
@@ -56,7 +65,12 @@
mBinder = binder;
}
- /** An interface describing the callback for bugreport progress and status. */
+ /**
+ * An interface describing the callback for bugreport progress and status.
+ *
+ * <p>In general, callers can expect to receive {@link #onProgress} calls as the bugreport
+ * progresses, followed by a terminal call to either {@link #onFinished} or {@link #onError}.
+ */
public abstract static class BugreportCallback {
/**
* Possible error codes taking a bugreport can encounter.
@@ -75,15 +89,18 @@
})
public @interface BugreportErrorCode {}
- /** The input options were invalid */
+ /**
+ * The input options were invalid. For example, the destination file the app provided could
+ * not be written by the system.
+ */
public static final int BUGREPORT_ERROR_INVALID_INPUT =
IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT;
- /** A runtime error occurred */
+ /** A runtime error occurred. */
public static final int BUGREPORT_ERROR_RUNTIME =
IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR;
- /** User denied consent to share the bugreport */
+ /** User denied consent to share the bugreport. */
public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT =
IDumpstateListener.BUGREPORT_ERROR_USER_DENIED_CONSENT;
@@ -149,6 +166,7 @@
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.DUMP)
+ @WorkerThread
public void startBugreport(
@NonNull ParcelFileDescriptor bugreportFd,
@Nullable ParcelFileDescriptor screenshotFd,
@@ -222,6 +240,7 @@
* @param callback callback for progress and status updates.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @WorkerThread
public void startConnectivityBugreport(
@NonNull ParcelFileDescriptor bugreportFd,
@NonNull @CallbackExecutor Executor executor,
@@ -247,6 +266,7 @@
* @throws SecurityException if trying to cancel another app's bugreport in progress
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @WorkerThread
public void cancelBugreport() {
try {
mBinder.cancelBugreport(-1 /* callingUid */, mContext.getOpPackageName());
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 93c1690..43184ea 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -26,6 +26,7 @@
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
@@ -631,10 +632,15 @@
/**
* Prepare to apply an unattended update by asking the user for their Lock Screen Knowledge
* Factor (LSKF). If supplied, the {@code intentSender} will be called when the system is setup
- * and ready to apply the OTA. This API is expected to handle requests from multiple clients
- * simultaneously, e.g. from ota and mainline.
+ * and ready to apply the OTA. <p>
*
- * <p> The behavior of multi-client Resume on Reboot works as follows
+ * <p> If the device doesn't setup a lock screen, i.e. by checking
+ * {@link KeyguardManager#isKeyguardSecure()}, this API call will fail and throw an exception.
+ * Callers are expected to use {@link PowerManager#reboot(String)} directly without going
+ * through the RoR flow. <p>
+ *
+ * <p> This API is expected to handle requests from multiple clients simultaneously, e.g.
+ * from ota and mainline. The behavior of multi-client Resume on Reboot works as follows
* <li> Each client should call this function to prepare for Resume on Reboot before calling
* {@link #rebootAndApply(Context, String, boolean)} </li>
* <li> One client cannot clear the Resume on Reboot preparation of another client. </li>
@@ -658,6 +664,13 @@
if (updateToken == null) {
throw new NullPointerException("updateToken == null");
}
+
+ KeyguardManager keyguardManager = context.getSystemService(KeyguardManager.class);
+ if (keyguardManager == null || !keyguardManager.isDeviceSecure()) {
+ throw new IOException("Failed to request LSKF because the device doesn't have a"
+ + " lock screen. ");
+ }
+
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
if (!rs.requestLskf(context.getPackageName(), intentSender)) {
throw new IOException("preparation for update failed");
diff --git a/core/java/android/os/incremental/IncrementalManager.java b/core/java/android/os/incremental/IncrementalManager.java
index cec6a1f..592e98a 100644
--- a/core/java/android/os/incremental/IncrementalManager.java
+++ b/core/java/android/os/incremental/IncrementalManager.java
@@ -241,10 +241,12 @@
}
/**
- * Checks if device supports V2 calls (e.g. PerUid).
+ * 0 - IncFs is disabled.
+ * 1 - IncFs v1, core features, no PerUid support. Optional in R.
+ * 2 - IncFs v2, PerUid support, fs-verity support. Required in S.
*/
- public static boolean isV2Available() {
- return nativeIsV2Available();
+ public static int getVersion() {
+ return nativeIsEnabled() ? nativeIsV2Available() ? 2 : 1 : 0;
}
/**
diff --git a/core/java/android/os/strictmode/IncorrectContextUseViolation.java b/core/java/android/os/strictmode/IncorrectContextUseViolation.java
index 11d26ca..d8c22fd 100644
--- a/core/java/android/os/strictmode/IncorrectContextUseViolation.java
+++ b/core/java/android/os/strictmode/IncorrectContextUseViolation.java
@@ -24,7 +24,7 @@
* instance.
*
* @see Context#getSystemService(String)
- * @see Context#isUiContext(Context)
+ * @see Context#isUiContext
* @see android.os.StrictMode.VmPolicy.Builder#detectIncorrectContextUse()
*/
public final class IncorrectContextUseViolation extends Violation {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ff10b0c..09d0af1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -417,6 +417,22 @@
"android.settings.MANAGE_UNKNOWN_APP_SOURCES";
/**
+ * Activity Action: Show settings to allow configuration of
+ * {@link Manifest.permission#SCHEDULE_EXACT_ALARM} permission
+ *
+ * Input: Optionally, the Intent's data URI can specify the application package name to
+ * directly invoke the management GUI specific to the package name. For example
+ * "package:com.my.app".
+ * <p>
+ * Output: When a package data uri is passed as input, the activity result is set to
+ * {@link android.app.Activity#RESULT_OK} if the permission was granted to the app. Otherwise,
+ * the result is set to {@link android.app.Activity#RESULT_CANCELED}.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_REQUEST_SCHEDULE_EXACT_ALARM =
+ "android.settings.REQUEST_SCHEDULE_EXACT_ALARM";
+
+ /**
* Activity Action: Show settings to allow configuration of cross-profile access for apps
*
* Input: Optionally, the Intent's data URI can specify the application package name to
diff --git a/core/java/android/provider/SimPhonebookContract.java b/core/java/android/provider/SimPhonebookContract.java
index 074d5f1..030b863 100644
--- a/core/java/android/provider/SimPhonebookContract.java
+++ b/core/java/android/provider/SimPhonebookContract.java
@@ -44,8 +44,11 @@
* The contract between the provider of contact records on the device's SIM cards and applications.
* Contains definitions of the supported URIs and columns.
*
- * <p>This content provider does not support any of the QUERY_ARG_SQL* bundle arguments. An
- * IllegalArgumentException will be thrown if these are included.
+ * <h3>Permissions</h3>
+ * <p>
+ * Querying this provider requires {@link android.Manifest.permission#READ_CONTACTS} and writing
+ * to this provider requires {@link android.Manifest.permission#WRITE_CONTACTS}
+ * </p>
*/
public final class SimPhonebookContract {
@@ -85,7 +88,73 @@
}
}
- /** Constants for the contact records on a SIM card. */
+ /**
+ * Constants for the contact records on a SIM card.
+ *
+ * <h3 id="simrecords-data">Data</h3>
+ * <p>
+ * Data is stored in a specific elementary file on a specific SIM card and these are isolated
+ * from each other. SIM cards are identified by their subscription ID. SIM cards may not support
+ * all or even any of the elementary file types. A SIM will have constraints on
+ * the values of the data that can be stored in each elementary file. The available SIMs,
+ * their supported elementary file types and the constraints on the data can be discovered by
+ * querying {@link ElementaryFiles#CONTENT_URI}. Each elementary file has a fixed capacity
+ * for the number of records that may be stored. This can be determined from the value
+ * of the {@link ElementaryFiles#MAX_RECORDS} column.
+ * </p>
+ * <p>
+ * The {@link SimRecords#PHONE_NUMBER} column can only contain dialable characters and this
+ * applies regardless of the SIM that is being used. See
+ * {@link android.telephony.PhoneNumberUtils#isDialable(char)} for more details. Additionally
+ * the phone number can contain at most {@link ElementaryFiles#PHONE_NUMBER_MAX_LENGTH}
+ * characters. The {@link SimRecords#NAME} column can contain at most
+ * {@link ElementaryFiles#NAME_MAX_LENGTH} bytes when it is encoded for storage on the SIM.
+ * Encoding is done internally and so the name should be provided unencoded but the number of
+ * bytes required to encode it will vary depending on the characters it contains. This length
+ * can be determined by calling
+ * {@link SimRecords#getEncodedNameLength(ContentResolver, String)}.
+ * </p>
+ * <h3>Operations </h3>
+ * <dl>
+ * <dd><b>Insert</b></dd>
+ * <p>
+ * Only {@link ElementaryFiles#EF_ADN} supports inserts. {@link SimRecords#PHONE_NUMBER}
+ * is a required column. If the value provided for this column is missing, null, empty
+ * or violates the requirements discussed in the <a href="#simrecords-data">Data</a>
+ * section above an {@link IllegalArgumentException} will be thrown. The
+ * {@link SimRecords#NAME} column may be omitted but if provided and it violates any of
+ * the requirements discussed in the <a href="#simrecords-data">Data</a> section above
+ * an {@link IllegalArgumentException} will be thrown.
+ * </p>
+ * <p>
+ * If an insert is not possible because the elementary file is full then an
+ * {@link IllegalStateException} will be thrown.
+ * </p>
+ * <dd><b>Update</b></dd>
+ * <p>
+ * Updates can only be performed for individual records on {@link ElementaryFiles#EF_ADN}.
+ * A specific record is referenced via the Uri returned by
+ * {@link SimRecords#getItemUri(int, int, int)}. Updates have the same constraints and
+ * behavior for the {@link SimRecords#PHONE_NUMBER} and {@link SimRecords#NAME} as insert.
+ * However, in the case of update the {@link SimRecords#PHONE_NUMBER} may be omitted as
+ * the existing record will already have a valid value.
+ * </p>
+ * <dd><b>Delete</b></dd>
+ * <p>
+ * Delete may only be performed for individual records on {@link ElementaryFiles#EF_ADN}.
+ * Deleting records will free up space for use by future inserts.
+ * </p>
+ * <dd><b>Query</b></dd>
+ * <p>
+ * All the records stored on a specific elementary file can be read via a Uri returned by
+ * {@link SimRecords#getContentUri(int, int)}. This query always returns all records; there
+ * is no support for filtering via a selection. An individual record can be queried via a Uri
+ * returned by {@link SimRecords#getItemUri(int, int, int)}. Queries will throw an
+ * {@link IllegalArgumentException} when the SIM with the subscription ID or the elementary file
+ * type are invalid or unavailable.
+ * </p>
+ * </dl>
+ */
public static final class SimRecords {
/**
@@ -197,8 +266,8 @@
* be discovered by querying {@link ElementaryFiles#CONTENT_URI}.
*
* <p>If a SIM with the provided subscription ID does not exist or the SIM with the provided
- * subscription ID doesn't support the specified entity file then queries will return
- * and empty cursor and inserts will throw an {@link IllegalArgumentException}
+ * subscription ID doesn't support the specified entity file then all operations will
+ * throw an {@link IllegalArgumentException}.
*
* @param subscriptionId the subscriptionId of the SIM card that this Uri will reference
* @param efType the elementary file on the SIM that this Uri will reference
@@ -233,6 +302,9 @@
* must be greater than 0. If there is no record with this record
* number in the specified entity file then it will be treated as a
* non-existent record.
+ * @see ElementaryFiles#SUBSCRIPTION_ID
+ * @see ElementaryFiles#EF_TYPE
+ * @see #RECORD_NUMBER
*/
@NonNull
public static Uri getItemUri(
@@ -287,7 +359,28 @@
}
- /** Constants for metadata about the elementary files of the SIM cards in the phone. */
+ /**
+ * Constants for metadata about the elementary files of the SIM cards in the phone.
+ *
+ * <h3>Operations </h3>
+ * <dl>
+ * <dd><b>Insert</b></dd>
+ * <p>Insert is not supported for the Uris defined in this class.</p>
+ * <dd><b>Update</b></dd>
+ * <p>Update is not supported for the Uris defined in this class.</p>
+ * <dd><b>Delete</b></dd>
+ * <p>Delete is not supported for the Uris defined in this class.</p>
+ * <dd><b>Query</b></dd>
+ * <p>
+ * The elementary files for all the inserted SIMs can be read via
+ * {@link ElementaryFiles#CONTENT_URI}. Unsupported elementary files are omitted from the
+ * results. This Uri always returns all supported elementary files for all available SIMs; it
+ * does not support filtering via a selection. A specific elementary file can be queried
+ * via a Uri returned by {@link ElementaryFiles#getItemUri(int, int)}. If the elementary file
+ * referenced by this Uri is unsupported by the SIM then the query will return an empty cursor.
+ * </p>
+ * </dl>
+ */
public static final class ElementaryFiles {
/** {@link SubscriptionInfo#getSimSlotIndex()} of the SIM for this row. */
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index ffb4a6e..3c355d4 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -270,13 +270,13 @@
/**
* Notify call state changed on certain subscription.
*
- * @param subId for which call state changed.
* @param slotIndex for which call state changed. Can be derived from subId except when subId is
* invalid.
+ * @param subId for which call state changed.
* @param state latest call state. e.g, offhook, ringing
* @param incomingNumber incoming phone number.
*/
- public void notifyCallStateChanged(int subId, int slotIndex, @CallState int state,
+ public void notifyCallStateChanged(int slotIndex, int subId, @CallState int state,
@Nullable String incomingNumber) {
try {
sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber);
@@ -329,12 +329,12 @@
/**
* Notify {@link ServiceState} update on certain subscription.
*
- * @param subId for which the service state changed.
* @param slotIndex for which the service state changed. Can be derived from subId except
* subId is invalid.
+ * @param subId for which the service state changed.
* @param state service state e.g, in service, out of service or roaming status.
*/
- public void notifyServiceStateChanged(int subId, int slotIndex, @NonNull ServiceState state) {
+ public void notifyServiceStateChanged(int slotIndex, int subId, @NonNull ServiceState state) {
try {
sRegistry.notifyServiceStateForPhoneId(slotIndex, subId, state);
} catch (RemoteException ex) {
@@ -345,12 +345,12 @@
/**
* Notify {@link SignalStrength} update on certain subscription.
*
- * @param subId for which the signalstrength changed.
* @param slotIndex for which the signalstrength changed. Can be derived from subId except when
* subId is invalid.
+ * @param subId for which the signalstrength changed.
* @param signalStrength e.g, signalstrength level {@see SignalStrength#getLevel()}
*/
- public void notifySignalStrengthChanged(int subId, int slotIndex,
+ public void notifySignalStrengthChanged(int slotIndex, int subId,
@NonNull SignalStrength signalStrength) {
try {
sRegistry.notifySignalStrengthForPhoneId(slotIndex, subId, signalStrength);
@@ -363,13 +363,13 @@
* Notify changes to the message-waiting indicator on certain subscription. e.g, The status bar
* uses message waiting indicator to determine when to display the voicemail icon.
*
- * @param subId for which message waiting indicator changed.
* @param slotIndex for which message waiting indicator changed. Can be derived from subId
* except when subId is invalid.
+ * @param subId for which message waiting indicator changed.
* @param msgWaitingInd {@code true} indicates there is message-waiting indicator, {@code false}
* otherwise.
*/
- public void notifyMessageWaitingChanged(int subId, int slotIndex, boolean msgWaitingInd) {
+ public void notifyMessageWaitingChanged(int slotIndex, int subId, boolean msgWaitingInd) {
try {
sRegistry.notifyMessageWaitingChangedForPhoneId(slotIndex, subId, msgWaitingInd);
} catch (RemoteException ex) {
@@ -410,9 +410,9 @@
/**
* Notify changes to default (Internet) data connection state on certain subscription.
*
- * @param subId for which data connection state changed.
* @param slotIndex for which data connections state changed. Can be derived from subId except
* when subId is invalid.
+ * @param subId for which data connection state changed.
* @param preciseState the PreciseDataConnectionState
*
* @see PreciseDataConnectionState
@@ -431,13 +431,13 @@
/**
* Notify {@link CallQuality} change on certain subscription.
*
- * @param subId for which call quality state changed.
* @param slotIndex for which call quality state changed. Can be derived from subId except when
* subId is invalid.
+ * @param subId for which call quality state changed.
* @param callQuality Information about call quality e.g, call quality level
* @param networkType associated with this data connection. e.g, LTE
*/
- public void notifyCallQualityChanged(int subId, int slotIndex, @NonNull CallQuality callQuality,
+ public void notifyCallQualityChanged(int slotIndex, int subId, @NonNull CallQuality callQuality,
@NetworkType int networkType) {
try {
sRegistry.notifyCallQualityChanged(callQuality, slotIndex, subId, networkType);
@@ -449,11 +449,11 @@
/**
* Notify emergency number list changed on certain subscription.
*
- * @param subId for which emergency number list changed.
* @param slotIndex for which emergency number list changed. Can be derived from subId except
* when subId is invalid.
+ * @param subId for which emergency number list changed.
*/
- public void notifyEmergencyNumberList(int subId, int slotIndex) {
+ public void notifyEmergencyNumberList( int slotIndex, int subId) {
try {
sRegistry.notifyEmergencyNumberList(slotIndex, subId);
} catch (RemoteException ex) {
@@ -494,13 +494,13 @@
/**
* Notify radio power state changed on certain subscription.
*
- * @param subId for which radio power state changed.
* @param slotIndex for which radio power state changed. Can be derived from subId except when
* subId is invalid.
+ * @param subId for which radio power state changed.
* @param radioPowerState the current modem radio state.
*/
- public void notifyRadioPowerStateChanged(int subId, int slotIndex,
- @RadioPowerState int radioPowerState) {
+ public void notifyRadioPowerStateChanged(int slotIndex, int subId,
+ @RadioPowerState int radioPowerState) {
try {
sRegistry.notifyRadioPowerStateChanged(slotIndex, subId, radioPowerState);
} catch (RemoteException ex) {
@@ -538,13 +538,13 @@
* Notify data activation state changed on certain subscription.
* @see TelephonyManager#getDataActivationState()
*
- * @param subId for which data activation state changed.
* @param slotIndex for which data activation state changed. Can be derived from subId except
* when subId is invalid.
+ * @param subId for which data activation state changed.
* @param activationState sim activation state e.g, activated.
*/
- public void notifyDataActivationStateChanged(int subId, int slotIndex,
- @SimActivationState int activationState) {
+ public void notifyDataActivationStateChanged(int slotIndex, int subId,
+ @SimActivationState int activationState) {
try {
sRegistry.notifySimActivationStateChangedForPhoneId(slotIndex, subId,
SIM_ACTIVATION_TYPE_DATA, activationState);
@@ -557,13 +557,13 @@
* Notify voice activation state changed on certain subscription.
* @see TelephonyManager#getVoiceActivationState()
*
- * @param subId for which voice activation state changed.
* @param slotIndex for which voice activation state changed. Can be derived from subId except
* subId is invalid.
+ * @param subId for which voice activation state changed.
* @param activationState sim activation state e.g, activated.
*/
- public void notifyVoiceActivationStateChanged(int subId, int slotIndex,
- @SimActivationState int activationState) {
+ public void notifyVoiceActivationStateChanged(int slotIndex, int subId,
+ @SimActivationState int activationState) {
try {
sRegistry.notifySimActivationStateChangedForPhoneId(slotIndex, subId,
SIM_ACTIVATION_TYPE_VOICE, activationState);
@@ -576,9 +576,9 @@
* Notify User mobile data state changed on certain subscription. e.g, mobile data is enabled
* or disabled.
*
- * @param subId for which mobile data state has changed.
* @param slotIndex for which mobile data state has changed. Can be derived from subId except
* when subId is invalid.
+ * @param subId for which mobile data state has changed.
* @param state {@code true} indicates mobile data is enabled/on. {@code false} otherwise.
*/
public void notifyUserMobileDataStateChanged(int slotIndex, int subId, boolean state) {
@@ -599,7 +599,7 @@
* @param telephonyDisplayInfo The display info.
*/
public void notifyDisplayInfoChanged(int slotIndex, int subscriptionId,
- @NonNull TelephonyDisplayInfo telephonyDisplayInfo) {
+ @NonNull TelephonyDisplayInfo telephonyDisplayInfo) {
try {
sRegistry.notifyDisplayInfoChanged(slotIndex, subscriptionId, telephonyDisplayInfo);
} catch (RemoteException ex) {
@@ -640,14 +640,14 @@
* Notify precise call state changed on certain subscription, including foreground, background
* and ringcall states.
*
- * @param subId for which precise call state changed.
* @param slotIndex for which precise call state changed. Can be derived from subId except when
* subId is invalid.
+ * @param subId for which precise call state changed.
* @param ringCallPreciseState ringCall state.
* @param foregroundCallPreciseState foreground call state.
* @param backgroundCallPreciseState background call state.
*/
- public void notifyPreciseCallState(int subId, int slotIndex,
+ public void notifyPreciseCallState(int slotIndex, int subId,
@PreciseCallStates int ringCallPreciseState,
@PreciseCallStates int foregroundCallPreciseState,
@PreciseCallStates int backgroundCallPreciseState) {
@@ -790,9 +790,10 @@
* @param reason Reason for data enabled/disabled. See {@code REASON_*} in
* {@link TelephonyManager}.
*/
- public void notifyDataEnabled(boolean enabled, @TelephonyManager.DataEnabledReason int reason) {
+ public void notifyDataEnabled(int slotIndex, int subId, boolean enabled,
+ @TelephonyManager.DataEnabledReason int reason) {
try {
- sRegistry.notifyDataEnabled(enabled, reason);
+ sRegistry.notifyDataEnabled(slotIndex, subId, enabled, reason);
} catch (RemoteException ex) {
// system server crash
}
@@ -801,11 +802,11 @@
/**
* Notify emergency number list changed on certain subscription.
*
- * @param subId for which emergency number list changed.
* @param slotIndex for which emergency number list changed. Can be derived from subId except
* when subId is invalid.
+ * @param subId for which emergency number list changed.
*/
- public void notifyAllowedNetworkTypesChanged(int subId, int slotIndex,
+ public void notifyAllowedNetworkTypesChanged(int slotIndex, int subId,
Map<Integer, Long> allowedNetworkTypeList) {
try {
sRegistry.notifyAllowedNetworkTypesChanged(slotIndex, subId, allowedNetworkTypeList);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b229212..2b577d0 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -46,6 +46,9 @@
"settings_do_not_restore_preserved";
/** @hide */
public static final String SETTINGS_PROVIDER_MODEL = "settings_provider_model";
+ /** @hide */
+ public static final String SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES
+ = "settings_use_new_backup_eligibility_rules";
private static final Map<String, String> DEFAULT_FLAGS;
@@ -68,6 +71,7 @@
DEFAULT_FLAGS.put("settings_silky_home", "false");
DEFAULT_FLAGS.put("settings_contextual_home", "false");
DEFAULT_FLAGS.put(SETTINGS_PROVIDER_MODEL, "false");
+ DEFAULT_FLAGS.put(SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES, "false");
}
private static final Set<String> PERSISTENT_FLAGS;
diff --git a/core/java/android/util/RotationUtils.java b/core/java/android/util/RotationUtils.java
index 698cb77..0ac2c9c 100644
--- a/core/java/android/util/RotationUtils.java
+++ b/core/java/android/util/RotationUtils.java
@@ -24,6 +24,7 @@
import android.annotation.Dimension;
import android.graphics.Insets;
import android.graphics.Matrix;
+import android.graphics.Rect;
import android.view.Surface.Rotation;
/**
@@ -73,6 +74,60 @@
}
/**
+ * Rotates bounds as if parentBounds and bounds are a group. The group is rotated from
+ * oldRotation to newRotation. This assumes that parentBounds is at 0,0 and remains at 0,0 after
+ * rotation. The bounds will be at the same physical position in parentBounds.
+ *
+ * Only 'inOutBounds' is mutated.
+ */
+ public static void rotateBounds(Rect inOutBounds, Rect parentBounds, @Rotation int oldRotation,
+ @Rotation int newRotation) {
+ rotateBounds(inOutBounds, parentBounds, deltaRotation(oldRotation, newRotation));
+ }
+
+ /**
+ * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta`
+ * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and
+ * remains at 0,0 after rotation. The bounds will be at the same physical position in
+ * parentBounds.
+ *
+ * Only 'inOutBounds' is mutated.
+ */
+ public static void rotateBounds(Rect inOutBounds, Rect parentBounds, @Rotation int rotation) {
+ final int origLeft = inOutBounds.left;
+ final int origTop = inOutBounds.top;
+ switch (rotation) {
+ case ROTATION_0:
+ return;
+ case ROTATION_90:
+ inOutBounds.left = inOutBounds.top;
+ inOutBounds.top = parentBounds.right - inOutBounds.right;
+ inOutBounds.right = inOutBounds.bottom;
+ inOutBounds.bottom = parentBounds.right - origLeft;
+ return;
+ case ROTATION_180:
+ inOutBounds.left = parentBounds.right - inOutBounds.right;
+ inOutBounds.right = parentBounds.right - origLeft;
+ inOutBounds.top = parentBounds.bottom - inOutBounds.bottom;
+ inOutBounds.bottom = parentBounds.bottom - origTop;
+ return;
+ case ROTATION_270:
+ inOutBounds.left = parentBounds.bottom - inOutBounds.bottom;
+ inOutBounds.bottom = inOutBounds.right;
+ inOutBounds.right = parentBounds.bottom - inOutBounds.top;
+ inOutBounds.top = origLeft;
+ }
+ }
+
+ /** @return the rotation needed to rotate from oldRotation to newRotation. */
+ @Rotation
+ public static int deltaRotation(int oldRotation, int newRotation) {
+ int delta = newRotation - oldRotation;
+ if (delta < 0) delta += 4;
+ return delta;
+ }
+
+ /**
* Sets a matrix such that given a rotation, it transforms physical display
* coordinates to that rotation's logical coordinates.
*
diff --git a/core/java/android/uwb/AngleOfArrivalSupport.aidl b/core/java/android/uwb/AngleOfArrivalSupport.aidl
deleted file mode 100644
index 57666ff..0000000
--- a/core/java/android/uwb/AngleOfArrivalSupport.aidl
+++ /dev/null
@@ -1,44 +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.uwb;
-
-/**
- * @hide
- */
-@Backing(type="int")
-enum AngleOfArrivalSupport {
- /**
- * The device does not support angle of arrival
- */
- NONE,
-
- /**
- * The device supports planar angle of arrival
- */
- TWO_DIMENSIONAL,
-
- /**
- * The device does supports three dimensional angle of arrival with hemispherical azimuth angles
- */
- THREE_DIMENSIONAL_HEMISPHERICAL,
-
- /**
- * The device does supports three dimensional angle of arrival with full azimuth angles
- */
- THREE_DIMENSIONAL_SPHERICAL,
-}
-
diff --git a/core/java/android/uwb/IUwbAdapter.aidl b/core/java/android/uwb/IUwbAdapter.aidl
index b9c5508..468a69c 100644
--- a/core/java/android/uwb/IUwbAdapter.aidl
+++ b/core/java/android/uwb/IUwbAdapter.aidl
@@ -17,7 +17,6 @@
package android.uwb;
import android.os.PersistableBundle;
-import android.uwb.AngleOfArrivalSupport;
import android.uwb.IUwbAdapterStateCallbacks;
import android.uwb.IUwbRangingCallbacks;
import android.uwb.SessionHandle;
@@ -47,43 +46,6 @@
void unregisterAdapterStateCallbacks(in IUwbAdapterStateCallbacks callbacks);
/**
- * Returns true if ranging is supported, false otherwise
- */
- boolean isRangingSupported();
-
- /**
- * Get the angle of arrival supported by this device
- *
- * @return the angle of arrival type supported
- */
- AngleOfArrivalSupport getAngleOfArrivalSupport();
-
- /**
- * Generates a list of the supported 802.15.4z channels
- *
- * The list must be prioritized in the order of preferred channel usage.
- *
- * The list must only contain channels that are permitted to be used in the
- * device's current location.
- *
- * @return an array of support channels on the device for the current location.
- */
- int[] getSupportedChannels();
-
- /**
- * Generates a list of the supported 802.15.4z preamble codes
- *
- * The list must be prioritized in the order of preferred preamble usage.
- *
- * The list must only contain preambles that are permitted to be used in the
- * device's current location.
- *
- * @return an array of supported preambles on the device for the current
- * location.
- */
- int[] getSupportedPreambleCodes();
-
- /**
* Get the accuracy of the ranging timestamps
*
* @return accuracy of the ranging timestamps in nanoseconds
@@ -91,27 +53,6 @@
long getTimestampResolutionNanos();
/**
- * Get the supported number of simultaneous ranging sessions
- *
- * @return the supported number of simultaneous ranging sessions
- */
- int getMaxSimultaneousSessions();
-
- /**
- * Get the maximum number of remote devices per session when local device is initiator
- *
- * @return the maximum number of remote devices supported in a single session
- */
- int getMaxRemoteDevicesPerInitiatorSession();
-
- /**
- * Get the maximum number of remote devices per session when local device is responder
- *
- * @return the maximum number of remote devices supported in a single session
- */
- int getMaxRemoteDevicesPerResponderSession();
-
- /**
* Provides the capabilities and features of the device
*
* @return specification specific capabilities and features of the device
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index 2dc0ba0..63a6d05 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -32,10 +32,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
import java.util.concurrent.Executor;
/**
@@ -195,133 +191,6 @@
}
/**
- * Check if ranging is supported, regardless of ranging method
- *
- * @return true if ranging is supported
- */
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public boolean isRangingSupported() {
- try {
- return mUwbAdapter.isRangingSupported();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(value = {
- ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE,
- ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D,
- ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL,
- ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL})
- public @interface AngleOfArrivalSupportType {}
-
- /**
- * Indicate absence of support for angle of arrival measurement
- */
- public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE = 1;
-
- /**
- * Indicate support for planar angle of arrival measurement, due to antenna
- * limitation. Typically requires at least two antennas.
- */
- public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D = 2;
-
- /**
- * Indicate support for three dimensional angle of arrival measurement.
- * Typically requires at least three antennas. However, due to antenna
- * arrangement, a platform may only support hemi-spherical azimuth angles
- * ranging from -pi/2 to pi/2
- */
- public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL = 3;
-
- /**
- * Indicate support for three dimensional angle of arrival measurement.
- * Typically requires at least three antennas. This mode supports full
- * azimuth angles ranging from -pi to pi.
- */
- public static final int ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL = 4;
-
- /**
- * Gets the {@link AngleOfArrivalSupportType} supported on this platform
- * <p>Possible return values are
- * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE},
- * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D},
- * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL},
- * {@link #ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL}.
- *
- * @return angle of arrival type supported
- */
- @AngleOfArrivalSupportType
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public int getAngleOfArrivalSupport() {
- try {
- switch (mUwbAdapter.getAngleOfArrivalSupport()) {
- case AngleOfArrivalSupport.TWO_DIMENSIONAL:
- return ANGLE_OF_ARRIVAL_SUPPORT_TYPE_2D;
-
- case AngleOfArrivalSupport.THREE_DIMENSIONAL_HEMISPHERICAL:
- return ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_HEMISPHERICAL;
-
- case AngleOfArrivalSupport.THREE_DIMENSIONAL_SPHERICAL:
- return ANGLE_OF_ARRIVAL_SUPPORT_TYPE_3D_SPHERICAL;
-
- case AngleOfArrivalSupport.NONE:
- default:
- return ANGLE_OF_ARRIVAL_SUPPORT_TYPE_NONE;
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get a {@link List} of supported channel numbers based on the device's current location
- * <p>The returned values are ordered by the system's desired ordered of use, with the first
- * entry being the most preferred.
- *
- * <p>Channel numbers are defined based on the IEEE 802.15.4z standard for UWB.
- *
- * @return {@link List} of supported channel numbers ordered by preference
- */
- @NonNull
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public List<Integer> getSupportedChannelNumbers() {
- List<Integer> channels = new ArrayList<>();
- try {
- for (int channel : mUwbAdapter.getSupportedChannels()) {
- channels.add(channel);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- return channels;
- }
-
- /**
- * Get a {@link List} of supported preamble code indices
- * <p> Preamble code indices are defined based on the IEEE 802.15.4z standard for UWB.
- *
- * @return {@link List} of supported preamble code indices
- */
- @NonNull
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public Set<Integer> getSupportedPreambleCodeIndices() {
- Set<Integer> preambles = new HashSet<>();
- try {
- for (int preamble : mUwbAdapter.getSupportedPreambleCodes()) {
- preambles.add(preamble);
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- return preambles;
- }
-
- /**
* Get the timestamp resolution for events in nanoseconds
* <p>This value defines the maximum error of all timestamps for events reported to
* {@link RangingSession.Callback}.
@@ -339,50 +208,6 @@
}
/**
- * Get the number of simultaneous sessions allowed in the system
- *
- * @return the maximum allowed number of simultaneously open {@link RangingSession} instances.
- */
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public int getMaxSimultaneousSessions() {
- try {
- return mUwbAdapter.getMaxSimultaneousSessions();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get the maximum number of remote devices in a {@link RangingSession} when the local device
- * is the initiator.
- *
- * @return the maximum number of remote devices per {@link RangingSession}
- */
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public int getMaxRemoteDevicesPerInitiatorSession() {
- try {
- return mUwbAdapter.getMaxRemoteDevicesPerInitiatorSession();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get the maximum number of remote devices in a {@link RangingSession} when the local device
- * is a responder.
- *
- * @return the maximum number of remote devices per {@link RangingSession}
- */
- @RequiresPermission(Manifest.permission.UWB_PRIVILEGED)
- public int getMaxRemoteDevicesPerResponderSession() {
- try {
- return mUwbAdapter.getMaxRemoteDevicesPerResponderSession();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Open a {@link RangingSession} with the given parameters
* <p>The {@link RangingSession.Callback#onOpened(RangingSession)} function is called with a
* {@link RangingSession} object used to control ranging when the session is successfully
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 8117c96..0ba1dfe 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -34,7 +34,6 @@
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
-import android.hardware.display.DeviceProductInfo;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
@@ -1182,18 +1181,6 @@
}
/**
- * Returns the product-specific information about the display or the directly connected
- * device on the display chain.
- * For example, if the display is transitively connected, this field may contain product
- * information about the intermediate device.
- * Returns {@code null} if product information is not available.
- */
- @Nullable
- public DeviceProductInfo getDeviceProductInfo() {
- return mDisplayInfo.deviceProductInfo;
- }
-
- /**
* Gets display metrics that describe the size and density of this display.
* The size returned by this method does not necessarily represent the
* actual raw size (native resolution) of the display.
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 6543de1..eb49e52 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -213,8 +213,7 @@
Index.FRAME_TIMELINE_VSYNC_ID,
Index.INTENDED_VSYNC,
Index.VSYNC,
- Index.OLDEST_INPUT_EVENT,
- Index.NEWEST_INPUT_EVENT,
+ Index.INPUT_EVENT_ID,
Index.HANDLE_INPUT_START,
Index.ANIMATION_START,
Index.PERFORM_TRAVERSALS_START,
@@ -225,8 +224,11 @@
Index.ISSUE_DRAW_COMMANDS_START,
Index.SWAP_BUFFERS,
Index.FRAME_COMPLETED,
+ Index.DEQUEUE_BUFFER_DURATION,
+ Index.QUEUE_BUFFER_DURATION,
Index.GPU_COMPLETED,
- Index.SWAP_BUFFERS_COMPLETED
+ Index.SWAP_BUFFERS_COMPLETED,
+ Index.DISPLAY_PRESENT_TIME,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Index {
@@ -234,20 +236,22 @@
int FRAME_TIMELINE_VSYNC_ID = 1;
int INTENDED_VSYNC = 2;
int VSYNC = 3;
- int OLDEST_INPUT_EVENT = 4;
- int NEWEST_INPUT_EVENT = 5;
- int HANDLE_INPUT_START = 6;
- int ANIMATION_START = 7;
- int PERFORM_TRAVERSALS_START = 8;
- int DRAW_START = 9;
- int FRAME_DEADLINE = 10;
- int SYNC_QUEUED = 11;
- int SYNC_START = 12;
- int ISSUE_DRAW_COMMANDS_START = 13;
- int SWAP_BUFFERS = 14;
- int FRAME_COMPLETED = 15;
- int GPU_COMPLETED = 18;
- int SWAP_BUFFERS_COMPLETED = 19;
+ int INPUT_EVENT_ID = 4;
+ int HANDLE_INPUT_START = 5;
+ int ANIMATION_START = 6;
+ int PERFORM_TRAVERSALS_START = 7;
+ int DRAW_START = 8;
+ int FRAME_DEADLINE = 9;
+ int SYNC_QUEUED = 10;
+ int SYNC_START = 11;
+ int ISSUE_DRAW_COMMANDS_START = 12;
+ int SWAP_BUFFERS = 13;
+ int FRAME_COMPLETED = 14;
+ int DEQUEUE_BUFFER_DURATION = 15;
+ int QUEUE_BUFFER_DURATION = 16;
+ int GPU_COMPLETED = 17;
+ int SWAP_BUFFERS_COMPLETED = 18;
+ int DISPLAY_PRESENT_TIME = 19;
int FRAME_STATS_COUNT = 20; // must always be last and in sync with
// FrameInfoIndex::NumIndexes in libs/hwui/FrameInfo.h
diff --git a/core/java/android/view/IPinnedStackListener.aidl b/core/java/android/view/IPinnedTaskListener.aidl
similarity index 95%
rename from core/java/android/view/IPinnedStackListener.aidl
rename to core/java/android/view/IPinnedTaskListener.aidl
index 29c9c15..c31e67e 100644
--- a/core/java/android/view/IPinnedStackListener.aidl
+++ b/core/java/android/view/IPinnedTaskListener.aidl
@@ -23,11 +23,11 @@
import android.view.DisplayInfo;
/**
- * Listener for changes to the pinned stack made by the WindowManager.
+ * Listener for changes to the pinned task made by the WindowManager.
*
* @hide
*/
-oneway interface IPinnedStackListener {
+oneway interface IPinnedTaskListener {
/**
* Called when the window manager has detected a change that would cause the movement bounds
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 4e4ba3f..afdf798 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -35,13 +35,12 @@
import android.view.DisplayCutout;
import android.view.IApplicationToken;
import android.view.IAppTransitionAnimationSpecsFuture;
-import android.view.IDockedStackListener;
import android.view.IDisplayWindowInsetsController;
import android.view.IDisplayWindowListener;
import android.view.IDisplayFoldListener;
import android.view.IDisplayWindowRotationController;
import android.view.IOnKeyguardExitResult;
-import android.view.IPinnedStackListener;
+import android.view.IPinnedTaskListener;
import android.view.IScrollCaptureCallbacks;
import android.view.RemoteAnimationAdapter;
import android.view.IRotationWatcher;
@@ -446,12 +445,12 @@
* Sets the region the user can touch the divider. This region will be excluded from the region
* which is used to cause a focus switch when dispatching touch.
*/
- void setDockedStackDividerTouchRegion(in Rect touchableRegion);
+ void setDockedTaskDividerTouchRegion(in Rect touchableRegion);
/**
- * Registers a listener that will be called when the pinned stack state changes.
+ * Registers a listener that will be called when the pinned task state changes.
*/
- void registerPinnedStackListener(int displayId, IPinnedStackListener listener);
+ void registerPinnedTaskListener(int displayId, IPinnedTaskListener listener);
/**
* Requests Keyboard Shortcuts from the displayed window.
diff --git a/core/java/android/view/SoundEffectConstants.java b/core/java/android/view/SoundEffectConstants.java
index 8d891bb..f177451 100644
--- a/core/java/android/view/SoundEffectConstants.java
+++ b/core/java/android/view/SoundEffectConstants.java
@@ -16,12 +16,21 @@
package android.view;
+import android.media.AudioManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+
+import java.util.Random;
+
/**
- * Constants to be used to play sound effects via {@link View#playSoundEffect(int)}
+ * Constants to be used to play sound effects via {@link View#playSoundEffect(int)}
*/
public class SoundEffectConstants {
private SoundEffectConstants() {}
+ private static final Random NAVIGATION_REPEAT_RANDOMIZER = new Random();
+ private static int sLastNavigationRepeatSoundEffectId = -1;
public static final int CLICK = 0;
@@ -29,6 +38,14 @@
public static final int NAVIGATION_UP = 2;
public static final int NAVIGATION_RIGHT = 3;
public static final int NAVIGATION_DOWN = 4;
+ /** Sound effect for a repeatedly triggered navigation, e.g. due to long pressing a button */
+ public static final int NAVIGATION_REPEAT_LEFT = 5;
+ /** @see #NAVIGATION_REPEAT_LEFT */
+ public static final int NAVIGATION_REPEAT_UP = 6;
+ /** @see #NAVIGATION_REPEAT_LEFT */
+ public static final int NAVIGATION_REPEAT_RIGHT = 7;
+ /** @see #NAVIGATION_REPEAT_LEFT */
+ public static final int NAVIGATION_REPEAT_DOWN = 8;
/**
* Get the sonification constant for the focus directions.
@@ -40,7 +57,7 @@
* @throws {@link IllegalArgumentException} when the passed direction is not one of the
* documented values.
*/
- public static int getContantForFocusDirection(int direction) {
+ public static int getContantForFocusDirection(@View.FocusDirection int direction) {
switch (direction) {
case View.FOCUS_RIGHT:
return SoundEffectConstants.NAVIGATION_RIGHT;
@@ -56,4 +73,65 @@
throw new IllegalArgumentException("direction must be one of "
+ "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}.");
}
+
+ /**
+ * Get the sonification constant for the focus directions
+ * @param direction One of {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
+ * {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, {@link View#FOCUS_FORWARD}
+ * or {@link View#FOCUS_BACKWARD}
+ * @param repeating True if the user long-presses a direction
+ * @return The appropriate sonification constant
+ * @throws IllegalArgumentException when the passed direction is not one of the
+ * documented values.
+ */
+ public static int getConstantForFocusDirection(@View.FocusDirection int direction,
+ boolean repeating) {
+ if (repeating) {
+ switch (direction) {
+ case View.FOCUS_RIGHT:
+ return SoundEffectConstants.NAVIGATION_REPEAT_RIGHT;
+ case View.FOCUS_FORWARD:
+ case View.FOCUS_DOWN:
+ return SoundEffectConstants.NAVIGATION_REPEAT_DOWN;
+ case View.FOCUS_LEFT:
+ return SoundEffectConstants.NAVIGATION_REPEAT_LEFT;
+ case View.FOCUS_BACKWARD:
+ case View.FOCUS_UP:
+ return SoundEffectConstants.NAVIGATION_REPEAT_UP;
+ }
+ throw new IllegalArgumentException("direction must be one of {FOCUS_UP, FOCUS_DOWN, "
+ + "FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}.");
+ } else {
+ return getContantForFocusDirection(direction);
+ }
+ }
+
+ /**
+ * @param effectId any of the effect ids defined in {@link SoundEffectConstants}
+ * @return true if the given effect id is a navigation repeat one
+ * @hide
+ */
+ @VisibleForTesting(visibility = Visibility.PACKAGE)
+ public static boolean isNavigationRepeat(int effectId) {
+ return effectId == SoundEffectConstants.NAVIGATION_REPEAT_DOWN
+ || effectId == SoundEffectConstants.NAVIGATION_REPEAT_LEFT
+ || effectId == SoundEffectConstants.NAVIGATION_REPEAT_RIGHT
+ || effectId == SoundEffectConstants.NAVIGATION_REPEAT_UP;
+ }
+
+ /**
+ * @return The next navigation repeat sound effect id, chosen at random in a non-repeating
+ * fashion
+ * @hide
+ */
+ @VisibleForTesting(visibility = Visibility.PACKAGE)
+ public static int nextNavigationRepeatSoundEffectId() {
+ int next = NAVIGATION_REPEAT_RANDOMIZER.nextInt(
+ AudioManager.NUM_NAVIGATION_REPEAT_SOUND_EFFECTS - 1);
+ if (next >= sLastNavigationRepeatSoundEffectId) {
+ next++;
+ }
+ sLastNavigationRepeatSoundEffectId = next;
+ return AudioManager.getNthNavigationRepeatSoundEffect(next);
+ }
}
diff --git a/core/java/android/view/SurfaceControlFpsListener.java b/core/java/android/view/SurfaceControlFpsListener.java
new file mode 100644
index 0000000..517b0fb
--- /dev/null
+++ b/core/java/android/view/SurfaceControlFpsListener.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.NonNull;
+
+/**
+ * Listener for sampling the frames per second for a SurfaceControl and its children.
+ * This should only be used by a system component that needs to listen to a SurfaceControl's
+ * tree's FPS when it is not actively submitting transactions for that SurfaceControl.
+ * Otherwise, ASurfaceTransaction_OnComplete callbacks should be used.
+ *
+ * @hide
+ */
+public abstract class SurfaceControlFpsListener {
+ private long mNativeListener;
+
+ public SurfaceControlFpsListener() {
+ mNativeListener = nativeCreate(this);
+ }
+
+ protected void destroy() {
+ if (mNativeListener == 0) {
+ return;
+ }
+ unregister();
+ nativeDestroy(mNativeListener);
+ mNativeListener = 0;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ destroy();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Reports the fps from the registered SurfaceControl
+ */
+ public abstract void onFpsReported(float fps);
+
+ /**
+ * Registers the sampling listener.
+ */
+ public void register(@NonNull SurfaceControl layer) {
+ if (mNativeListener == 0) {
+ return;
+ }
+
+ nativeRegister(mNativeListener, layer.mNativeObject);
+ }
+
+ /**
+ * Unregisters the sampling listener.
+ */
+ public void unregister() {
+ if (mNativeListener == 0) {
+ return;
+ }
+ nativeUnregister(mNativeListener);
+ }
+
+ /**
+ * Dispatch the collected sample.
+ *
+ * Called from native code on a binder thread.
+ */
+ private static void dispatchOnFpsReported(SurfaceControlFpsListener listener, float fps) {
+ listener.onFpsReported(fps);
+ }
+
+ private static native long nativeCreate(SurfaceControlFpsListener thiz);
+ private static native void nativeDestroy(long ptr);
+ private static native void nativeRegister(long ptr, long layerObject);
+ private static native void nativeUnregister(long ptr);
+}
diff --git a/core/java/android/view/ViewFrameInfo.java b/core/java/android/view/ViewFrameInfo.java
index 890d071..d4aaa61 100644
--- a/core/java/android/view/ViewFrameInfo.java
+++ b/core/java/android/view/ViewFrameInfo.java
@@ -58,8 +58,8 @@
public void populateFrameInfo(FrameInfo frameInfo) {
frameInfo.frameInfo[FrameInfo.FLAGS] |= flags;
frameInfo.frameInfo[FrameInfo.DRAW_START] = drawStart;
- frameInfo.frameInfo[FrameInfo.OLDEST_INPUT_EVENT] = oldestInputEventTime;
- frameInfo.frameInfo[FrameInfo.NEWEST_INPUT_EVENT] = newestInputEventTime;
+ // TODO(b/169866723): Use InputEventAssigner
+ frameInfo.frameInfo[FrameInfo.INPUT_EVENT_ID] = newestInputEventTime;
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 144691d..1abcb15 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -323,6 +323,8 @@
private boolean mForceDisableBLAST;
private boolean mEnableTripleBuffering;
+ private boolean mFastScrollSoundEffectsEnabled;
+
/**
* Signals that compatibility booleans have been initialized according to
* target SDK versions.
@@ -813,6 +815,8 @@
loadSystemProperties();
mImeFocusController = new ImeFocusController(this);
+ AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+ mFastScrollSoundEffectsEnabled = audioManager.areNavigationRepeatSoundEffectsEnabled();
}
public static void addFirstDrawHandler(Runnable callback) {
@@ -6081,8 +6085,10 @@
v, mTempRect);
}
if (v.requestFocus(direction, mTempRect)) {
- playSoundEffect(SoundEffectConstants
- .getContantForFocusDirection(direction));
+ boolean isFastScrolling = event.getRepeatCount() > 0;
+ playSoundEffect(
+ SoundEffectConstants.getConstantForFocusDirection(direction,
+ isFastScrolling));
return true;
}
}
@@ -7743,20 +7749,31 @@
try {
final AudioManager audioManager = getAudioManager();
+ if (mFastScrollSoundEffectsEnabled
+ && SoundEffectConstants.isNavigationRepeat(effectId)) {
+ audioManager.playSoundEffect(
+ SoundEffectConstants.nextNavigationRepeatSoundEffectId());
+ return;
+ }
+
switch (effectId) {
case SoundEffectConstants.CLICK:
audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
return;
case SoundEffectConstants.NAVIGATION_DOWN:
+ case SoundEffectConstants.NAVIGATION_REPEAT_DOWN:
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
return;
case SoundEffectConstants.NAVIGATION_LEFT:
+ case SoundEffectConstants.NAVIGATION_REPEAT_LEFT:
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_LEFT);
return;
case SoundEffectConstants.NAVIGATION_RIGHT:
+ case SoundEffectConstants.NAVIGATION_REPEAT_RIGHT:
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_RIGHT);
return;
case SoundEffectConstants.NAVIGATION_UP:
+ case SoundEffectConstants.NAVIGATION_REPEAT_UP:
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_UP);
return;
default:
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 05b177e..39c09b4 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -6612,6 +6612,27 @@
}
/**
+ * Returns the {@link EdgeEffect#getType()} for the edge effects.
+ * @return the {@link EdgeEffect#getType()} for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ @EdgeEffect.EdgeEffectType
+ public int getEdgeEffectType() {
+ return mEdgeGlowTop.getType();
+ }
+
+ /**
+ * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+ * @param type The edge effect type to use for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+ mEdgeGlowTop.setType(type);
+ mEdgeGlowBottom.setType(type);
+ invalidate();
+ }
+
+ /**
* Sets the recycler listener to be notified whenever a View is set aside in
* the recycler for later reuse. This listener can be used to free resources
* associated to the View.
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 6dedd12..23915e0 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -303,6 +303,27 @@
}
/**
+ * Returns the {@link EdgeEffect#getType()} for the edge effects.
+ * @return the {@link EdgeEffect#getType()} for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ @EdgeEffect.EdgeEffectType
+ public int getEdgeEffectType() {
+ return mEdgeGlowLeft.getType();
+ }
+
+ /**
+ * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+ * @param type The edge effect type to use for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+ mEdgeGlowRight.setType(type);
+ mEdgeGlowLeft.setType(type);
+ invalidate();
+ }
+
+ /**
* @return The maximum amount this scroll view will scroll in response to
* an arrow event.
*/
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 5144717..e0b4ec7 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -46,6 +46,8 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.content.res.loader.ResourcesLoader;
+import android.content.res.loader.ResourcesProvider;
import android.graphics.Bitmap;
import android.graphics.BlendMode;
import android.graphics.Outline;
@@ -62,16 +64,19 @@
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.Process;
import android.os.StrictMode;
import android.os.UserHandle;
+import android.system.Os;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.IntArray;
import android.util.Log;
import android.util.Pair;
+import android.util.SparseIntArray;
import android.util.TypedValue;
import android.util.TypedValue.ComplexDimensionUnit;
import android.view.ContextThemeWrapper;
@@ -92,6 +97,12 @@
import com.android.internal.util.ContrastColorUtil;
import com.android.internal.util.Preconditions;
+import java.io.ByteArrayOutputStream;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -520,8 +531,8 @@
* SUBCLASSES MUST BE IMMUTABLE SO CLONE WORKS!!!!!
*/
private abstract static class Action implements Parcelable {
- public abstract void apply(View root, ViewGroup rootParent,
- InteractionHandler handler) throws ActionException;
+ public abstract void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) throws ActionException;
public static final int MERGE_REPLACE = 0;
public static final int MERGE_APPEND = 1;
@@ -551,8 +562,8 @@
* and return the final action which will run on the UI thread.
* Override this if some of the tasks can be performed async.
*/
- public Action initActionAsync(
- ViewTree root, ViewGroup rootParent, InteractionHandler handler) {
+ public Action initActionAsync(ViewTree root, ViewGroup rootParent,
+ InteractionHandler handler, ColorResources colorResources) {
return this;
}
@@ -595,7 +606,9 @@
// Constant used during async execution. It is not parcelable.
private static final Action ACTION_NOOP = new RuntimeAction() {
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) { }
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
+ }
};
/**
@@ -713,7 +726,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View view = root.findViewById(viewId);
if (!(view instanceof AdapterView<?>)) return;
@@ -748,7 +762,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, final InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -820,7 +835,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -843,7 +859,8 @@
if (a instanceof RemoteViewsListAdapter && viewTypeCount <= a.getViewTypeCount()) {
((RemoteViewsListAdapter) a).setViewsList(list);
} else {
- v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount));
+ v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount,
+ colorResources));
}
} else if (target instanceof AdapterViewAnimator) {
AdapterViewAnimator v = (AdapterViewAnimator) target;
@@ -851,7 +868,8 @@
if (a instanceof RemoteViewsListAdapter && viewTypeCount <= a.getViewTypeCount()) {
((RemoteViewsListAdapter) a).setViewsList(list);
} else {
- v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount));
+ v.setAdapter(new RemoteViewsListAdapter(v.getContext(), list, viewTypeCount,
+ colorResources));
}
}
}
@@ -882,7 +900,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -919,7 +938,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler) {
+ InteractionHandler handler, ColorResources colorResources) {
SetRemoteViewsAdapterIntent copy = new SetRemoteViewsAdapterIntent(viewId, intent);
copy.isAsync = true;
return copy;
@@ -958,7 +977,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, final InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -1037,7 +1057,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, final InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, final InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
if (!(target instanceof CompoundButton)) {
@@ -1240,7 +1261,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -1297,7 +1319,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -1334,7 +1357,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View view = root.findViewById(viewId);
if (view == null) return;
@@ -1437,12 +1461,12 @@
}
@Override
- public void apply(View root, ViewGroup rootParent,
- InteractionHandler handler) throws ActionException {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) throws ActionException {
ReflectionAction ra = new ReflectionAction(viewId, methodName,
BaseReflectionAction.BITMAP,
bitmap);
- ra.apply(root, rootParent, handler);
+ ra.apply(root, rootParent, handler, colorResources);
}
@Override
@@ -1518,7 +1542,8 @@
protected abstract Object getParameterValue(@Nullable View view) throws ActionException;
@Override
- public final void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public final void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View view = root.findViewById(viewId);
if (view == null) return;
@@ -1536,7 +1561,7 @@
@Override
public final Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler) {
+ InteractionHandler handler, ColorResources colorResources) {
final View view = root.findViewById(viewId);
if (view == null) return ACTION_NOOP;
@@ -1938,7 +1963,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
mRunnable.run();
}
}
@@ -1993,7 +2019,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final Context context = root.getContext();
final ViewGroup target = root.findViewById(viewId);
@@ -2002,12 +2029,14 @@
}
// Inflate nested views and add as children
- target.addView(mNestedViews.apply(context, target, handler), mIndex);
+ target.addView(
+ mNestedViews.apply(context, target, handler, null /* size */, colorResources),
+ mIndex);
}
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler) {
+ InteractionHandler handler, ColorResources colorResources) {
// In the async implementation, update the view tree so that subsequent calls to
// findViewById return the current view.
root.createTree();
@@ -2019,8 +2048,8 @@
// Inflate nested views and perform all the async tasks for the child remoteView.
final Context context = root.mRoot.getContext();
- final AsyncApplyTask task = mNestedViews.getAsyncApplyTask(
- context, targetVg, null, handler);
+ final AsyncApplyTask task = mNestedViews.getAsyncApplyTask(context, targetVg,
+ null /* listener */, handler, null /* size */, colorResources);
final ViewTree tree = task.doInBackground();
if (tree == null) {
@@ -2033,8 +2062,8 @@
return new RuntimeAction() {
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler)
- throws ActionException {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) throws ActionException {
task.onPostExecute(tree);
targetVg.addView(task.mResult, mIndex);
}
@@ -2095,7 +2124,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final ViewGroup target = root.findViewById(viewId);
if (target == null) {
@@ -2112,7 +2142,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler) {
+ InteractionHandler handler, ColorResources colorResources) {
// In the async implementation, update the view tree so that subsequent calls to
// findViewById return the current view.
root.createTree();
@@ -2136,8 +2166,8 @@
}
return new RuntimeAction() {
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler)
- throws ActionException {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) throws ActionException {
if (mViewIdToKeep == REMOVE_ALL_VIEWS_ID) {
targetVg.removeAllViews();
return;
@@ -2192,7 +2222,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null || target == root) {
@@ -2207,7 +2238,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler) {
+ InteractionHandler handler, ColorResources colorResources) {
// In the async implementation, update the view tree so that subsequent calls to
// findViewById return the correct view.
root.createTree();
@@ -2226,8 +2257,8 @@
parent.mChildren.remove(target);
return new RuntimeAction() {
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler)
- throws ActionException {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) throws ActionException {
parentVg.removeView(target.mRoot);
}
};
@@ -2306,7 +2337,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final TextView target = root.findViewById(viewId);
if (target == null) return;
if (drawablesLoaded) {
@@ -2337,7 +2369,7 @@
@Override
public Action initActionAsync(ViewTree root, ViewGroup rootParent,
- InteractionHandler handler) {
+ InteractionHandler handler, ColorResources colorResources) {
final TextView target = root.findViewById(viewId);
if (target == null) return ACTION_NOOP;
@@ -2415,7 +2447,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final TextView target = root.findViewById(viewId);
if (target == null) return;
target.setTextSize(units, size);
@@ -2460,7 +2493,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
target.setPadding(left, top, right, bottom);
@@ -2533,7 +2567,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) {
return;
@@ -2646,7 +2681,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -2681,7 +2717,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
// Let's traverse the viewtree and override all textColors!
Stack<View> viewsToProcess = new Stack<>();
viewsToProcess.add(root);
@@ -2731,7 +2768,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler) {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) {
final View target = root.findViewById(mViewId);
if (target == null) return;
@@ -2765,7 +2803,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler)
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources)
throws ActionException {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -2816,8 +2855,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler)
- throws ActionException {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) throws ActionException {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -2893,8 +2932,8 @@
}
@Override
- public void apply(View root, ViewGroup rootParent, InteractionHandler handler)
- throws ActionException {
+ public void apply(View root, ViewGroup rootParent, InteractionHandler handler,
+ ColorResources colorResources) throws ActionException {
final View target = root.findViewById(viewId);
if (target == null) return;
@@ -4662,7 +4701,7 @@
RemoteViews rvToApply = getRemoteViewsToApply(context, size);
View result = inflateView(context, rvToApply, parent);
- rvToApply.performApply(result, parent, handler);
+ rvToApply.performApply(result, parent, handler, null);
return result;
}
@@ -4674,27 +4713,39 @@
/** @hide */
public View applyWithTheme(@NonNull Context context, @NonNull ViewGroup parent,
- @Nullable InteractionHandler handler,
- @StyleRes int applyThemeResId,
+ @Nullable InteractionHandler handler, @StyleRes int applyThemeResId,
@Nullable PointF size) {
RemoteViews rvToApply = getRemoteViewsToApply(context, size);
- View result = inflateView(context, rvToApply, parent, applyThemeResId);
- rvToApply.performApply(result, parent, handler);
+ View result = inflateView(context, rvToApply, parent, applyThemeResId, null);
+ rvToApply.performApply(result, parent, handler, null);
+ return result;
+ }
+
+ /** @hide */
+ public View apply(Context context, ViewGroup parent, InteractionHandler handler,
+ @NonNull PointF size, @Nullable ColorResources colorResources) {
+ RemoteViews rvToApply = getRemoteViewsToApply(context, size);
+
+ View result = inflateView(context, rvToApply, parent, 0, colorResources);
+ rvToApply.performApply(result, parent, handler, colorResources);
return result;
}
private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
- return inflateView(context, rv, parent, 0);
+ return inflateView(context, rv, parent, 0, null);
}
private View inflateView(Context context, RemoteViews rv, ViewGroup parent,
- @StyleRes int applyThemeResId) {
+ @StyleRes int applyThemeResId, @Nullable ColorResources colorResources) {
// RemoteViews may be built by an application installed in another
// user. So build a context that loads resources from that user but
// still returns the current users userId so settings like data / time formats
// are loaded without requiring cross user persmissions.
final Context contextForResources = getContextForResources(context);
+ if (colorResources != null) {
+ colorResources.apply(contextForResources);
+ }
Context inflationContext = new RemoteViewsContextWrapper(context, contextForResources);
// If mApplyThemeResId is not given, Theme.DeviceDefault will be used.
@@ -4756,34 +4807,37 @@
*/
public CancellationSignal applyAsync(
Context context, ViewGroup parent, Executor executor, OnViewAppliedListener listener) {
- return applyAsync(context, parent, executor, listener, null);
+ return applyAsync(context, parent, executor, listener, null /* handler */);
}
/** @hide */
public CancellationSignal applyAsync(Context context, ViewGroup parent,
Executor executor, OnViewAppliedListener listener, InteractionHandler handler) {
- return applyAsync(context, parent, executor, listener, handler, null);
+ return applyAsync(context, parent, executor, listener, handler, null /* size */);
}
/** @hide */
public CancellationSignal applyAsync(Context context, ViewGroup parent,
Executor executor, OnViewAppliedListener listener, InteractionHandler handler,
PointF size) {
- return getAsyncApplyTask(context, parent, listener, handler, size).startTaskOnExecutor(
- executor);
+ return getAsyncApplyTask(context, parent, listener, handler, size, null /* themeColors */)
+ .startTaskOnExecutor(executor);
+ }
+
+ /** @hide */
+ public CancellationSignal applyAsync(Context context, ViewGroup parent, Executor executor,
+ OnViewAppliedListener listener, InteractionHandler handler, PointF size,
+ ColorResources colorResources) {
+ return getAsyncApplyTask(context, parent, listener, handler, size, colorResources)
+ .startTaskOnExecutor(executor);
}
private AsyncApplyTask getAsyncApplyTask(Context context, ViewGroup parent,
- OnViewAppliedListener listener, InteractionHandler handler) {
- return getAsyncApplyTask(context, parent, listener, handler, null);
- }
-
- private AsyncApplyTask getAsyncApplyTask(Context context, ViewGroup parent,
- OnViewAppliedListener listener, InteractionHandler handler, PointF size) {
- return new AsyncApplyTask(getRemoteViewsToApply(context, size), parent, context,
- listener,
- handler, null);
+ OnViewAppliedListener listener, InteractionHandler handler, PointF size,
+ ColorResources colorResources) {
+ return new AsyncApplyTask(getRemoteViewsToApply(context, size), parent, context, listener,
+ handler, colorResources, null /* result */);
}
private class AsyncApplyTask extends AsyncTask<Void, Void, ViewTree>
@@ -4794,6 +4848,7 @@
final Context mContext;
final OnViewAppliedListener mListener;
final InteractionHandler mHandler;
+ final ColorResources mColorResources;
private View mResult;
private ViewTree mTree;
@@ -4802,11 +4857,12 @@
private AsyncApplyTask(
RemoteViews rv, ViewGroup parent, Context context, OnViewAppliedListener listener,
- InteractionHandler handler, View result) {
+ InteractionHandler handler, ColorResources colorResources, View result) {
mRV = rv;
mParent = parent;
mContext = context;
mListener = listener;
+ mColorResources = colorResources;
mHandler = handler;
mResult = result;
@@ -4816,7 +4872,7 @@
protected ViewTree doInBackground(Void... params) {
try {
if (mResult == null) {
- mResult = inflateView(mContext, mRV, mParent);
+ mResult = inflateView(mContext, mRV, mParent, 0, mColorResources);
}
mTree = new ViewTree(mResult);
@@ -4825,7 +4881,8 @@
mActions = new Action[count];
for (int i = 0; i < count && !isCancelled(); i++) {
// TODO: check if isCancelled in nested views.
- mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler);
+ mActions[i] = mRV.mActions.get(i).initActionAsync(mTree, mParent, mHandler,
+ mColorResources);
}
} else {
mActions = null;
@@ -4850,7 +4907,7 @@
InteractionHandler handler = mHandler == null
? DEFAULT_INTERACTION_HANDLER : mHandler;
for (Action a : mActions) {
- a.apply(viewTree.mRoot, mParent, handler);
+ a.apply(viewTree.mRoot, mParent, handler, mColorResources);
}
}
} catch (Exception e) {
@@ -4894,16 +4951,17 @@
* the {@link #apply(Context,ViewGroup)} call.
*/
public void reapply(Context context, View v) {
- reapply(context, v, null, null);
+ reapply(context, v, null /* handler */);
}
/** @hide */
public void reapply(Context context, View v, InteractionHandler handler) {
- reapply(context, v, handler, null);
+ reapply(context, v, handler, null /* size */, null /* colorResources */);
}
/** @hide */
- public void reapply(Context context, View v, InteractionHandler handler, PointF size) {
+ public void reapply(Context context, View v, InteractionHandler handler, PointF size,
+ ColorResources colorResources) {
RemoteViews rvToApply = getRemoteViewsToApply(context, size);
// In the case that a view has this RemoteViews applied in one orientation or size, is
@@ -4917,7 +4975,7 @@
}
}
- rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);
+ rvToApply.performApply(v, (ViewGroup) v.getParent(), handler, colorResources);
}
/**
@@ -4933,20 +4991,21 @@
* @return CancellationSignal
* @hide
*/
- public CancellationSignal reapplyAsync(
- Context context, View v, Executor executor, OnViewAppliedListener listener) {
- return reapplyAsync(context, v, executor, listener, null, null);
+ public CancellationSignal reapplyAsync(Context context, View v, Executor executor,
+ OnViewAppliedListener listener) {
+ return reapplyAsync(context, v, executor, listener, null);
}
/** @hide */
public CancellationSignal reapplyAsync(Context context, View v, Executor executor,
OnViewAppliedListener listener, InteractionHandler handler) {
- return reapplyAsync(context, v, executor, listener, handler, null);
+ return reapplyAsync(context, v, executor, listener, handler, null, null);
}
/** @hide */
public CancellationSignal reapplyAsync(Context context, View v, Executor executor,
- OnViewAppliedListener listener, InteractionHandler handler, PointF size) {
+ OnViewAppliedListener listener, InteractionHandler handler, PointF size,
+ ColorResources colorResources) {
RemoteViews rvToApply = getRemoteViewsToApply(context, size);
// In the case that a view has this RemoteViews applied in one orientation, is persisted
@@ -4960,16 +5019,18 @@
}
return new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
- context, listener, handler, v).startTaskOnExecutor(executor);
+ context, listener, handler, colorResources, v).startTaskOnExecutor(
+ executor);
}
- private void performApply(View v, ViewGroup parent, InteractionHandler handler) {
+ private void performApply(View v, ViewGroup parent, InteractionHandler handler,
+ ColorResources colorResources) {
if (mActions != null) {
handler = handler == null ? DEFAULT_INTERACTION_HANDLER : handler;
final int count = mActions.size();
for (int i = 0; i < count; i++) {
Action a = mActions.get(i);
- a.apply(v, parent, handler);
+ a.apply(v, parent, handler, colorResources);
}
}
}
@@ -5010,6 +5071,122 @@
}
/**
+ * Object allowing the modification of a context to overload the system's dynamic colors.
+ *
+ * Only colors from {@link android.R.color#system_primary_0} to
+ * {@link android.R.color#system_neutral_1000} can be overloaded.
+ * @hide
+ */
+ public static final class ColorResources {
+ // Set of valid colors resources.
+ private static final int FIRST_RESOURCE_COLOR_ID = android.R.color.system_primary_0;
+ private static final int LAST_RESOURCE_COLOR_ID = android.R.color.system_neutral_1000;
+ // Size, in bytes, of an entry in the array of colors in an ARSC file.
+ private static final int ARSC_ENTRY_SIZE = 16;
+
+ private ResourcesLoader mLoader;
+
+ private ColorResources(ResourcesLoader loader) {
+ mLoader = loader;
+ }
+
+ /**
+ * Apply the color resources to the given context.
+ *
+ * No resource resolution must have be done on the context given to that method.
+ */
+ public void apply(Context context) {
+ context.getResources().addLoaders(mLoader);
+ }
+
+ private static ByteArrayOutputStream readFileContent(InputStream input) throws IOException {
+ ByteArrayOutputStream content = new ByteArrayOutputStream(2048);
+ byte[] buffer = new byte[4096];
+ while (input.available() > 0) {
+ int read = input.read(buffer);
+ content.write(buffer, 0, read);
+ }
+ return content;
+ }
+
+ /**
+ * Creates the compiled resources content from the asset stored in the APK.
+ *
+ * The asset is a compiled resource with the correct resources name and correct ids, only
+ * the values are incorrect. The last value is at the very end of the file. The resources
+ * are in an array, the array's entries are 16 bytes each. We use this to work out the
+ * location of all the positions of the various resources.
+ */
+ private static byte[] createCompiledResourcesContent(Context context,
+ SparseIntArray colorResources) throws IOException {
+ byte[] content;
+ try (InputStream input = context.getResources().openRawResource(
+ com.android.internal.R.raw.remote_views_color_resources)) {
+ ByteArrayOutputStream rawContent = readFileContent(input);
+ content = rawContent.toByteArray();
+ }
+ int valuesOffset =
+ content.length - (LAST_RESOURCE_COLOR_ID & 0xffff) * ARSC_ENTRY_SIZE - 4;
+ if (valuesOffset < 0) {
+ Log.e(LOG_TAG, "ARSC file for theme colors is invalid.");
+ return null;
+ }
+ for (int colorRes = FIRST_RESOURCE_COLOR_ID; colorRes <= LAST_RESOURCE_COLOR_ID;
+ colorRes++) {
+ // The last 2 bytes are the index in the color array.
+ int index = colorRes & 0xffff;
+ int offset = valuesOffset + index * ARSC_ENTRY_SIZE;
+ int value = colorResources.get(colorRes, context.getColor(colorRes));
+ // Write the 32 bit integer in little endian
+ for (int b = 0; b < 4; b++) {
+ content[offset + b] = (byte) (value & 0xff);
+ value >>= 8;
+ }
+ }
+ return content;
+ }
+
+ /**
+ * Adds a resource loader for theme colors to the given context.
+ *
+ * @param context Context of the view hosting the widget.
+ * @param colorMapping Mapping of resources to color values.
+ *
+ * @hide
+ */
+ public static ColorResources create(Context context, SparseIntArray colorMapping) {
+ try {
+ byte[] contentBytes = createCompiledResourcesContent(context, colorMapping);
+ if (contentBytes == null) {
+ return null;
+ }
+ FileDescriptor arscFile = null;
+ try {
+ arscFile = Os.memfd_create("remote_views_theme_colors.arsc", 0 /* flags */);
+ // Note: This must not be closed through the OutputStream.
+ try (OutputStream pipeWriter = new FileOutputStream(arscFile)) {
+ pipeWriter.write(contentBytes);
+
+ try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(arscFile)) {
+ ResourcesLoader colorsLoader = new ResourcesLoader();
+ colorsLoader.addProvider(ResourcesProvider
+ .loadFromTable(pfd, null /* assetsProvider */));
+ return new ColorResources(colorsLoader);
+ }
+ }
+ } finally {
+ if (arscFile != null) {
+ Os.close(arscFile);
+ }
+ }
+ } catch (Exception ex) {
+ Log.e(LOG_TAG, "Failed to setup the context for theme colors", ex);
+ }
+ return null;
+ }
+ }
+
+ /**
* Returns the number of actions in this RemoteViews. Can be used as a sequence number.
*
* @hide
diff --git a/core/java/android/widget/RemoteViewsListAdapter.java b/core/java/android/widget/RemoteViewsListAdapter.java
index b80fe48..827d033 100644
--- a/core/java/android/widget/RemoteViewsListAdapter.java
+++ b/core/java/android/widget/RemoteViewsListAdapter.java
@@ -31,12 +31,14 @@
private ArrayList<RemoteViews> mRemoteViewsList;
private ArrayList<Integer> mViewTypes = new ArrayList<Integer>();
private int mViewTypeCount;
+ private RemoteViews.ColorResources mColorResources;
public RemoteViewsListAdapter(Context context, ArrayList<RemoteViews> remoteViews,
- int viewTypeCount) {
+ int viewTypeCount, RemoteViews.ColorResources colorResources) {
mContext = context;
mRemoteViewsList = remoteViews;
mViewTypeCount = viewTypeCount;
+ mColorResources = colorResources;
init();
}
@@ -90,9 +92,10 @@
if (convertView != null && rv != null &&
convertView.getId() == rv.getLayoutId()) {
v = convertView;
- rv.reapply(mContext, v);
+ rv.reapply(mContext, v, null /* handler */, null /* size */, mColorResources);
} else {
- v = rv.apply(mContext, parent);
+ v = rv.apply(mContext, parent, null /* handler */, null /* size */,
+ mColorResources);
}
return v;
} else {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 64d09de..65f3da7 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -335,6 +335,27 @@
}
/**
+ * Returns the {@link EdgeEffect#getType()} for the edge effects.
+ * @return the {@link EdgeEffect#getType()} for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ @EdgeEffect.EdgeEffectType
+ public int getEdgeEffectType() {
+ return mEdgeGlowTop.getType();
+ }
+
+ /**
+ * Sets the {@link EdgeEffect#setType(int)} for the edge effects.
+ * @param type The edge effect type to use for the edge effects.
+ * @attr ref android.R.styleable#EdgeEffect_edgeEffectType
+ */
+ public void setEdgeEffectType(@EdgeEffect.EdgeEffectType int type) {
+ mEdgeGlowTop.setType(type);
+ mEdgeGlowBottom.setType(type);
+ invalidate();
+ }
+
+ /**
* @return The maximum amount this scroll view will scroll in response to
* an arrow event.
*/
diff --git a/core/java/android/widget/ToastPresenter.java b/core/java/android/widget/ToastPresenter.java
index 2904a8c..0f2a3ca 100644
--- a/core/java/android/widget/ToastPresenter.java
+++ b/core/java/android/widget/ToastPresenter.java
@@ -184,7 +184,7 @@
mParams.y = yOffset;
mParams.horizontalMargin = horizontalMargin;
mParams.verticalMargin = verticalMargin;
- addToastView();
+ mView.setLayoutParams(mParams);
}
/**
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index e82cc73..342456a 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -25,6 +25,9 @@
import static android.view.SurfaceControl.JankData.PREDICTION_ERROR;
import static android.view.SurfaceControl.JankData.SURFACE_FLINGER_SCHEDULING;
+import static com.android.internal.jank.InteractionJankMonitor.ACTION_METRICS_LOGGED;
+import static com.android.internal.jank.InteractionJankMonitor.ACTION_SESSION_BEGIN;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.HardwareRendererObserver;
@@ -72,6 +75,7 @@
private long mEndVsyncId = INVALID_ID;
private boolean mMetricsFinalized;
private boolean mCancelled = false;
+ private FrameTrackerListener mListener;
private static class JankInfo {
long frameVsyncId;
@@ -109,7 +113,7 @@
@NonNull SurfaceControlWrapper surfaceControlWrapper,
@NonNull ChoreographerWrapper choreographer,
@NonNull FrameMetricsWrapper metrics, int traceThresholdMissedFrames,
- int traceThresholdFrameTimeMillis) {
+ int traceThresholdFrameTimeMillis, @Nullable FrameTrackerListener listener) {
mSession = session;
mRendererWrapper = renderer;
mMetricsWrapper = metrics;
@@ -120,6 +124,7 @@
mObserver = new HardwareRendererObserver(this, mMetricsWrapper.getTiming(), handler);
mTraceThresholdMissedFrames = traceThresholdMissedFrames;
mTraceThresholdFrameTimeMillis = traceThresholdFrameTimeMillis;
+ mListener = listener;
// If the surface isn't valid yet, wait until it's created.
if (viewRootWrapper.getSurfaceControl().isValid()) {
@@ -165,11 +170,15 @@
*/
public synchronized void begin() {
mBeginVsyncId = mChoreographer.getVsyncId() + 1;
+ mSession.setTimeStamp(System.nanoTime());
Trace.beginAsyncSection(mSession.getName(), (int) mBeginVsyncId);
mRendererWrapper.addObserver(mObserver);
if (mSurfaceControl != null) {
mSurfaceControlWrapper.addJankStatsListener(this, mSurfaceControl);
}
+ if (mListener != null) {
+ mListener.onNotifyCujEvents(mSession, ACTION_SESSION_BEGIN);
+ }
}
/**
@@ -224,7 +233,6 @@
}
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.
@@ -371,6 +379,9 @@
missedAppFramesCount + missedSfFramesCounts,
maxFrameTimeNanos,
missedSfFramesCounts);
+ if (mListener != null) {
+ mListener.onNotifyCujEvents(mSession, ACTION_METRICS_LOGGED);
+ }
}
if (DEBUG) {
Log.i(TAG, "FrameTracker: CUJ=" + mSession.getName()
@@ -495,4 +506,17 @@
return mChoreographer.getVsyncId();
}
}
+
+ /**
+ * A listener that notifies cuj events.
+ */
+ public interface FrameTrackerListener {
+ /**
+ * Notify that the CUJ session was created.
+ *
+ * @param session the CUJ session
+ * @param action the specific action
+ */
+ void onNotifyCujEvents(Session session, String action);
+ }
}
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index cba6af9..0294ec3 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -16,6 +16,8 @@
package com.android.internal.jank;
+import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY;
+
import static com.android.internal.jank.FrameTracker.ChoreographerWrapper;
import static com.android.internal.jank.FrameTracker.SurfaceControlWrapper;
import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_ALL_APPS_SCROLL;
@@ -48,9 +50,12 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Intent;
import android.os.Build;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
+import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.util.Log;
import android.util.SparseArray;
@@ -59,6 +64,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.FrameTracker.FrameMetricsWrapper;
+import com.android.internal.jank.FrameTracker.FrameTrackerListener;
import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper;
import com.android.internal.jank.FrameTracker.ViewRootWrapper;
import com.android.internal.util.PerfettoTrigger;
@@ -74,6 +80,8 @@
*/
public class InteractionJankMonitor {
private static final String TAG = InteractionJankMonitor.class.getSimpleName();
+ private static final String ACTION_PREFIX = InteractionJankMonitor.class.getCanonicalName();
+
private static final String DEFAULT_WORKER_NAME = TAG + "-Worker";
private static final long DEFAULT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5L);
private static final String SETTINGS_ENABLED_KEY = "enabled";
@@ -90,6 +98,14 @@
private static final int DEFAULT_TRACE_THRESHOLD_MISSED_FRAMES = 3;
private static final int DEFAULT_TRACE_THRESHOLD_FRAME_TIME_MILLIS = 64;
+ public static final String ACTION_SESSION_BEGIN = ACTION_PREFIX + ".ACTION_SESSION_BEGIN";
+ public static final String ACTION_SESSION_END = ACTION_PREFIX + ".ACTION_SESSION_END";
+ public static final String ACTION_METRICS_LOGGED = ACTION_PREFIX + ".ACTION_METRICS_LOGGED";
+ public static final String BUNDLE_KEY_CUJ_NAME = ACTION_PREFIX + ".CUJ_NAME";
+ public static final String BUNDLE_KEY_TIMESTAMP = ACTION_PREFIX + ".TIMESTAMP";
+ @VisibleForTesting
+ public static final String PROP_NOTIFY_CUJ_EVENT = "debug.notify_cuj_events";
+
// Every value must have a corresponding entry in CUJ_STATSD_INTERACTION_TYPE.
public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE = 0;
public static final int CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE_LOCK = 1;
@@ -256,15 +272,28 @@
*/
@VisibleForTesting
public FrameTracker createFrameTracker(View v, Session session) {
+ final Context c = v.getContext().getApplicationContext();
synchronized (this) {
+ boolean needListener = SystemProperties.getBoolean(PROP_NOTIFY_CUJ_EVENT, false);
+ FrameTrackerListener eventsListener =
+ !needListener ? null : (s, act) -> notifyEvents(c, act, s);
+
return new FrameTracker(session, mWorker.getThreadHandler(),
new ThreadedRendererWrapper(v.getThreadedRenderer()),
new ViewRootWrapper(v.getViewRootImpl()), new SurfaceControlWrapper(),
new ChoreographerWrapper(Choreographer.getInstance()), mMetrics,
- mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis);
+ mTraceThresholdMissedFrames, mTraceThresholdFrameTimeMillis, eventsListener);
}
}
+ private void notifyEvents(Context context, String action, Session session) {
+ Intent intent = new Intent(action);
+ intent.putExtra(BUNDLE_KEY_CUJ_NAME, getNameOfCuj(session.getCuj()));
+ intent.putExtra(BUNDLE_KEY_TIMESTAMP, session.getTimeStamp());
+ intent.addFlags(FLAG_RECEIVER_REGISTERED_ONLY);
+ context.sendBroadcast(intent);
+ }
+
/**
* Begin a trace session.
*
@@ -479,6 +508,7 @@
public static class Session {
@CujType
private int mCujType;
+ private long mTimeStamp;
public Session(@CujType int cujType) {
mCujType = cujType;
@@ -505,5 +535,13 @@
public String getName() {
return "J<" + getNameOfCuj(mCujType) + ">";
}
+
+ public void setTimeStamp(long timeStamp) {
+ mTimeStamp = timeStamp;
+ }
+
+ public long getTimeStamp() {
+ return mTimeStamp;
+ }
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1f8ffe0..54095bd 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12520,6 +12520,7 @@
* @param totalEnergyUJ energy (microjoules) used for this bucket since this was last called.
* @param uidEnergies map of uid->energy (microjoules) for this bucket since last called.
* Data inside uidEnergies will not be modified (treated immutable).
+ * Uids not already known to BatteryStats will be ignored.
*/
public void updateCustomMeasuredEnergyDataLocked(int customEnergyBucket,
long totalEnergyUJ, @Nullable SparseLongArray uidEnergies) {
@@ -12540,10 +12541,20 @@
final int uidInt = mapUid(uidEnergies.keyAt(i));
final long uidEnergyUJ = uidEnergies.valueAt(i);
if (uidEnergyUJ == 0) continue;
- // TODO(b/180030409): Worry about dead Uids (no longer in BSI) being revived by this,
- // or converse problem of not creating a new Uid if its first blame is recorded here.
- final Uid uidObj = getUidStatsLocked(uidInt);
- uidObj.addEnergyToCustomBucketLocked(uidEnergyUJ, customEnergyBucket, true);
+ final Uid uidObj = getAvailableUidStatsLocked(uidInt);
+ if (uidObj != null) {
+ uidObj.addEnergyToCustomBucketLocked(uidEnergyUJ, customEnergyBucket, true);
+ } else {
+ // Ignore any uid not already known to BatteryStats, rather than creating a new Uid.
+ // Otherwise we could end up reviving dead Uids. Note that the CPU data is updated
+ // first, so any uid that has used any CPU should already be known to BatteryStats.
+ // Recently removed uids (especially common for isolated uids) can reach this path
+ // and are ignored.
+ if (!Process.isIsolated(uidInt)) {
+ Slog.w(TAG, "Received measured energy " + totalEnergyUJ + " for custom bucket "
+ + customEnergyBucket + " for non-existent uid " + uidInt);
+ }
+ }
}
}
diff --git a/core/java/com/android/internal/os/UsageBasedPowerEstimator.java b/core/java/com/android/internal/os/UsageBasedPowerEstimator.java
index 5910b61..fd52014 100644
--- a/core/java/com/android/internal/os/UsageBasedPowerEstimator.java
+++ b/core/java/com/android/internal/os/UsageBasedPowerEstimator.java
@@ -32,6 +32,10 @@
mAveragePowerMahPerMs = averagePowerMilliAmp / MILLIS_IN_HOUR;
}
+ public boolean isSupported() {
+ return mAveragePowerMahPerMs != 0;
+ }
+
/**
* Given a {@link BatteryStats.Timer}, returns the accumulated duration.
*/
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 63763f7..98f613f 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -15,8 +15,13 @@
*/
package com.android.internal.os;
+import android.os.BatteryConsumer;
import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArray;
@@ -30,25 +35,93 @@
public class WifiPowerCalculator extends PowerCalculator {
private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
private static final String TAG = "WifiPowerCalculator";
- private final double mIdleCurrentMa;
- private final double mTxCurrentMa;
- private final double mRxCurrentMa;
- private final PowerProfile mPowerProfile;
+ private final UsageBasedPowerEstimator mIdlePowerEstimator;
+ private final UsageBasedPowerEstimator mTxPowerEstimator;
+ private final UsageBasedPowerEstimator mRxPowerEstimator;
+ private final UsageBasedPowerEstimator mPowerOnPowerEstimator;
+ private final UsageBasedPowerEstimator mScanPowerEstimator;
+ private final UsageBasedPowerEstimator mBatchScanPowerEstimator;
private final boolean mHasWifiPowerController;
- private double mTotalAppPowerDrain = 0;
- private long mTotalAppRunningTime = 0;
- private WifiPowerEstimator mWifiPowerEstimator;
- private boolean mHasWifiPowerReporting;
+ private final double mWifiPowerPerPacket;
+
+ private static class PowerDurationAndTraffic {
+ public double powerMah;
+ public long durationMs;
+
+ public long wifiRxPackets;
+ public long wifiTxPackets;
+ public long wifiRxBytes;
+ public long wifiTxBytes;
+ }
public WifiPowerCalculator(PowerProfile profile) {
- mPowerProfile = profile;
+ mPowerOnPowerEstimator = new UsageBasedPowerEstimator(
+ profile.getAveragePower(PowerProfile.POWER_WIFI_ON));
+ mScanPowerEstimator = new UsageBasedPowerEstimator(
+ profile.getAveragePower(PowerProfile.POWER_WIFI_SCAN));
+ mBatchScanPowerEstimator = new UsageBasedPowerEstimator(
+ profile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN));
+ mIdlePowerEstimator = new UsageBasedPowerEstimator(
+ profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE));
+ mTxPowerEstimator = new UsageBasedPowerEstimator(
+ profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX));
+ mRxPowerEstimator = new UsageBasedPowerEstimator(
+ profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX));
- mIdleCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
- mTxCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX);
- mRxCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX);
+ mWifiPowerPerPacket = getWifiPowerPerPacket(profile);
- mHasWifiPowerController = mIdleCurrentMa != 0 && mTxCurrentMa != 0 && mRxCurrentMa != 0;
- mWifiPowerEstimator = new WifiPowerEstimator(mPowerProfile);
+ mHasWifiPowerController =
+ mIdlePowerEstimator.isSupported() && mTxPowerEstimator.isSupported()
+ && mRxPowerEstimator.isSupported();
+ }
+
+ @Override
+ public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+ long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+
+ // batteryStats.hasWifiActivityReporting can change if we get energy data at a later point,
+ // so always check this field.
+ final boolean hasWifiPowerReporting =
+ mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
+
+ final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
+ builder.getOrCreateSystemBatteryConsumerBuilder(
+ SystemBatteryConsumer.DRAIN_TYPE_WIFI);
+
+ long totalAppDurationMs = 0;
+ double totalAppPowerMah = 0;
+ final PowerDurationAndTraffic powerDurationAndTraffic = new PowerDurationAndTraffic();
+ final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
+ builder.getUidBatteryConsumerBuilders();
+ for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
+ final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
+ calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), rawRealtimeUs,
+ BatteryStats.STATS_SINCE_CHARGED,
+ hasWifiPowerReporting);
+
+ totalAppDurationMs += powerDurationAndTraffic.durationMs;
+ totalAppPowerMah += powerDurationAndTraffic.powerMah;
+
+ app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
+ powerDurationAndTraffic.durationMs);
+ app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI,
+ powerDurationAndTraffic.powerMah);
+
+ if (app.getUid() == Process.WIFI_UID) {
+ systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
+ app.excludeFromBatteryUsageStats();
+ }
+ }
+
+ calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs,
+ BatteryStats.STATS_SINCE_CHARGED,
+ hasWifiPowerReporting, totalAppDurationMs, totalAppPowerMah);
+
+ systemBatteryConsumerBuilder
+ .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
+ powerDurationAndTraffic.durationMs)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI,
+ powerDurationAndTraffic.powerMah);
}
/**
@@ -64,100 +137,151 @@
// batteryStats.hasWifiActivityReporting can change if we get energy data at a later point,
// so always check this field.
- mHasWifiPowerReporting = mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
+ final boolean hasWifiPowerReporting =
+ mHasWifiPowerController && batteryStats.hasWifiActivityReporting();
- super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
+ final BatterySipper bs = new BatterySipper(BatterySipper.DrainType.WIFI, null, 0);
- BatterySipper bs = new BatterySipper(BatterySipper.DrainType.WIFI, null, 0);
- calculateRemaining(bs, batteryStats, rawRealtimeUs, rawUptimeUs, statsType);
-
+ long totalAppDurationMs = 0;
+ double totalAppPowerMah = 0;
+ final PowerDurationAndTraffic powerDurationAndTraffic = new PowerDurationAndTraffic();
for (int i = sippers.size() - 1; i >= 0; i--) {
- BatterySipper app = sippers.get(i);
- if (app.getUid() == Process.WIFI_UID) {
- if (DEBUG) Log.d(TAG, "WiFi adding sipper " + app + ": cpu=" + app.cpuTimeMs);
- app.isAggregated = true;
- bs.add(app);
+ final BatterySipper app = sippers.get(i);
+ if (app.drainType == BatterySipper.DrainType.APP) {
+ calculateApp(powerDurationAndTraffic, app.uidObj, rawRealtimeUs, statsType,
+ hasWifiPowerReporting);
+
+ totalAppDurationMs += powerDurationAndTraffic.durationMs;
+ totalAppPowerMah += powerDurationAndTraffic.powerMah;
+
+ app.wifiPowerMah = powerDurationAndTraffic.powerMah;
+ app.wifiRunningTimeMs = powerDurationAndTraffic.durationMs;
+ app.wifiRxBytes = powerDurationAndTraffic.wifiRxBytes;
+ app.wifiRxPackets = powerDurationAndTraffic.wifiRxPackets;
+ app.wifiTxBytes = powerDurationAndTraffic.wifiTxBytes;
+ app.wifiTxPackets = powerDurationAndTraffic.wifiTxPackets;
+ if (app.getUid() == Process.WIFI_UID) {
+ if (DEBUG) Log.d(TAG, "WiFi adding sipper " + app + ": cpu=" + app.cpuTimeMs);
+ app.isAggregated = true;
+ bs.add(app);
+ }
}
}
+
+ calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs, statsType,
+ hasWifiPowerReporting, totalAppDurationMs, totalAppPowerMah);
+
+ bs.wifiRunningTimeMs += powerDurationAndTraffic.durationMs;
+ bs.wifiPowerMah += powerDurationAndTraffic.powerMah;
+
if (bs.sumPower() > 0) {
sippers.add(bs);
}
}
- @Override
- protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
- long rawUptimeUs, int statsType) {
- if (!mHasWifiPowerReporting) {
- mWifiPowerEstimator.calculateApp(app, u, rawRealtimeUs, rawUptimeUs, statsType);
- return;
- }
-
- final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
- if (counter == null) {
- return;
- }
-
- final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
- final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType);
- final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
- app.wifiRunningTimeMs = idleTime + rxTime + txTime;
- mTotalAppRunningTime += app.wifiRunningTimeMs;
-
- app.wifiPowerMah =
- ((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa))
- / (1000 * 60 * 60);
- mTotalAppPowerDrain += app.wifiPowerMah;
-
- app.wifiRxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
+ private void calculateApp(PowerDurationAndTraffic powerDurationAndTraffic, BatteryStats.Uid u,
+ long rawRealtimeUs,
+ int statsType, boolean hasWifiPowerReporting) {
+ powerDurationAndTraffic.wifiRxPackets = u.getNetworkActivityPackets(
+ BatteryStats.NETWORK_WIFI_RX_DATA,
statsType);
- app.wifiTxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
+ powerDurationAndTraffic.wifiTxPackets = u.getNetworkActivityPackets(
+ BatteryStats.NETWORK_WIFI_TX_DATA,
statsType);
- app.wifiRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
+ powerDurationAndTraffic.wifiRxBytes = u.getNetworkActivityBytes(
+ BatteryStats.NETWORK_WIFI_RX_DATA,
statsType);
- app.wifiTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
+ powerDurationAndTraffic.wifiTxBytes = u.getNetworkActivityBytes(
+ BatteryStats.NETWORK_WIFI_TX_DATA,
statsType);
- if (DEBUG && app.wifiPowerMah != 0) {
- Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime + "ms tx=" +
- txTime + "ms power=" + formatCharge(app.wifiPowerMah));
+ if (hasWifiPowerReporting) {
+ final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
+ if (counter != null) {
+ final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
+ final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+ final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
+
+ powerDurationAndTraffic.durationMs = idleTime + rxTime + txTime;
+ powerDurationAndTraffic.powerMah = mIdlePowerEstimator.calculatePower(idleTime)
+ + mTxPowerEstimator.calculatePower(txTime)
+ + mRxPowerEstimator.calculatePower(rxTime);
+
+ if (DEBUG && powerDurationAndTraffic.powerMah != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime
+ + "ms tx=" + txTime + "ms power=" + formatCharge(
+ powerDurationAndTraffic.powerMah));
+ }
+ }
+ } else {
+ final double wifiPacketPower = (
+ powerDurationAndTraffic.wifiRxPackets + powerDurationAndTraffic.wifiTxPackets)
+ * mWifiPowerPerPacket;
+ final long wifiRunningTime = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
+ final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
+ long batchScanTimeMs = 0;
+ for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
+ batchScanTimeMs += u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
+ }
+
+ powerDurationAndTraffic.durationMs = wifiRunningTime;
+ powerDurationAndTraffic.powerMah = wifiPacketPower
+ + mPowerOnPowerEstimator.calculatePower(wifiRunningTime)
+ + mScanPowerEstimator.calculatePower(wifiScanTimeMs)
+ + mBatchScanPowerEstimator.calculatePower(batchScanTimeMs);
+
+ if (DEBUG && powerDurationAndTraffic.powerMah != 0) {
+ Log.d(TAG, "UID " + u.getUid() + ": power=" + formatCharge(
+ powerDurationAndTraffic.powerMah));
+ }
}
}
- private void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
- long rawUptimeUs, int statsType) {
- if (!mHasWifiPowerReporting) {
- mWifiPowerEstimator.calculateRemaining(app, stats, rawRealtimeUs, rawUptimeUs,
- statsType);
- return;
+ private void calculateRemaining(PowerDurationAndTraffic powerDurationAndTraffic,
+ BatteryStats stats, long rawRealtimeUs,
+ int statsType, boolean hasWifiPowerReporting, long totalAppDurationMs,
+ double totalAppPowerMah) {
+ long totalDurationMs;
+ double totalPowerMah;
+ if (hasWifiPowerReporting) {
+ final BatteryStats.ControllerActivityCounter counter =
+ stats.getWifiControllerActivity();
+
+ final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
+ final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
+ final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
+
+ totalDurationMs = idleTimeMs + rxTimeMs + txTimeMs;
+
+ totalPowerMah =
+ counter.getPowerCounter().getCountLocked(statsType) / (double) (1000 * 60 * 60);
+ if (totalPowerMah == 0) {
+ // Some controllers do not report power drain, so we can calculate it here.
+ totalPowerMah = mIdlePowerEstimator.calculatePower(idleTimeMs)
+ + mTxPowerEstimator.calculatePower(txTimeMs)
+ + mRxPowerEstimator.calculatePower(rxTimeMs);
+ }
+ } else {
+ totalDurationMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType) / 1000;
+ totalPowerMah = mPowerOnPowerEstimator.calculatePower(totalDurationMs);
}
- final BatteryStats.ControllerActivityCounter counter = stats.getWifiControllerActivity();
-
- final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
- final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
- final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
-
- app.wifiRunningTimeMs = Math.max(0,
- (idleTimeMs + rxTimeMs + txTimeMs) - mTotalAppRunningTime);
-
- double powerDrainMah = counter.getPowerCounter().getCountLocked(statsType)
- / (double) (1000 * 60 * 60);
- if (powerDrainMah == 0) {
- // Some controllers do not report power drain, so we can calculate it here.
- powerDrainMah = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa)
- + (rxTimeMs * mRxCurrentMa)) / (1000 * 60 * 60);
- }
- app.wifiPowerMah = Math.max(0, powerDrainMah - mTotalAppPowerDrain);
+ powerDurationAndTraffic.durationMs = Math.max(0, totalDurationMs - totalAppDurationMs);
+ powerDurationAndTraffic.powerMah = Math.max(0, totalPowerMah - totalAppPowerMah);
if (DEBUG) {
- Log.d(TAG, "left over WiFi power: " + formatCharge(app.wifiPowerMah));
+ Log.d(TAG, "left over WiFi power: " + formatCharge(powerDurationAndTraffic.powerMah));
}
}
- @Override
- public void reset() {
- mTotalAppPowerDrain = 0;
- mTotalAppRunningTime = 0;
- mWifiPowerEstimator.reset();
+ /**
+ * Return estimated power per Wi-Fi packet in mAh/packet where 1 packet = 2 KB.
+ */
+ private static double getWifiPowerPerPacket(PowerProfile profile) {
+ // TODO(b/179392913): Extract average bit rates from system
+ final long wifiBps = 1000000;
+ final double averageWifiActivePower =
+ profile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE) / 3600;
+ return averageWifiActivePower / (((double) wifiBps) / 8 / 2048);
}
}
diff --git a/core/java/com/android/internal/os/WifiPowerEstimator.java b/core/java/com/android/internal/os/WifiPowerEstimator.java
deleted file mode 100644
index d0a105c..0000000
--- a/core/java/com/android/internal/os/WifiPowerEstimator.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.os;
-
-import android.os.BatteryStats;
-import android.os.Process;
-import android.os.UserHandle;
-import android.util.Log;
-import android.util.SparseArray;
-
-import java.util.List;
-
-/**
- * Estimates WiFi power usage based on timers in BatteryStats.
- */
-public class WifiPowerEstimator extends PowerCalculator {
- private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
- private static final String TAG = "WifiPowerEstimator";
- private final double mWifiPowerPerPacket;
- private final double mWifiPowerOn;
- private final double mWifiPowerScan;
- private final double mWifiPowerBatchScan;
- private long mTotalAppWifiRunningTimeMs = 0;
-
- public WifiPowerEstimator(PowerProfile profile) {
- mWifiPowerPerPacket = getWifiPowerPerPacket(profile);
- mWifiPowerOn = profile.getAveragePower(PowerProfile.POWER_WIFI_ON);
- mWifiPowerScan = profile.getAveragePower(PowerProfile.POWER_WIFI_SCAN);
- mWifiPowerBatchScan = profile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN);
- }
-
- @Override
- public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
- long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
- super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
-
- BatterySipper bs = new BatterySipper(BatterySipper.DrainType.WIFI, null, 0);
- calculateRemaining(bs, batteryStats, rawRealtimeUs, rawUptimeUs, statsType);
-
- for (int i = sippers.size() - 1; i >= 0; i--) {
- BatterySipper app = sippers.get(i);
- if (app.getUid() == Process.WIFI_UID) {
- if (DEBUG) Log.d(TAG, "WiFi adding sipper " + app + ": cpu=" + app.cpuTimeMs);
- app.isAggregated = true;
- bs.add(app);
- }
- }
- if (bs.sumPower() > 0) {
- sippers.add(bs);
- }
- }
-
- /**
- * Return estimated power per Wi-Fi packet in mAh/packet where 1 packet = 2 KB.
- */
- private static double getWifiPowerPerPacket(PowerProfile profile) {
- final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
- final double WIFI_POWER = profile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
- / 3600;
- return WIFI_POWER / (((double)WIFI_BPS) / 8 / 2048);
- }
-
- @Override
- protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
- long rawUptimeUs, int statsType) {
- app.wifiRxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
- statsType);
- app.wifiTxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
- statsType);
- app.wifiRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
- statsType);
- app.wifiTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
- statsType);
-
- final double wifiPacketPower = (app.wifiRxPackets + app.wifiTxPackets)
- * mWifiPowerPerPacket;
-
- app.wifiRunningTimeMs = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
- mTotalAppWifiRunningTimeMs += app.wifiRunningTimeMs;
- final double wifiLockPower = (app.wifiRunningTimeMs * mWifiPowerOn) / (1000*60*60);
-
- final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
- final double wifiScanPower = (wifiScanTimeMs * mWifiPowerScan) / (1000*60*60);
-
- double wifiBatchScanPower = 0;
- for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
- final long batchScanTimeMs =
- u.getWifiBatchedScanTime(bin, rawRealtimeUs, statsType) / 1000;
- final double batchScanPower = (batchScanTimeMs * mWifiPowerBatchScan) / (1000*60*60);
- wifiBatchScanPower += batchScanPower;
- }
-
- app.wifiPowerMah = wifiPacketPower + wifiLockPower + wifiScanPower + wifiBatchScanPower;
- if (DEBUG && app.wifiPowerMah != 0) {
- Log.d(TAG, "UID " + u.getUid() + ": power=" + formatCharge(app.wifiPowerMah));
- }
- }
-
- void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
- long rawUptimeUs, int statsType) {
- final long totalRunningTimeMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType)
- / 1000;
- final double powerDrain = ((totalRunningTimeMs - mTotalAppWifiRunningTimeMs) * mWifiPowerOn)
- / (1000*60*60);
- app.wifiRunningTimeMs = totalRunningTimeMs;
- app.wifiPowerMah = Math.max(0, powerDrain);
- }
-
- @Override
- public void reset() {
- mTotalAppWifiRunningTimeMs = 0;
- }
-}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 7edc6c8..fde48e8 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -67,7 +67,7 @@
void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message, int userId);
void onClearAllNotifications(int userId);
- void onNotificationClear(String pkg, String tag, int id, int userId, String key,
+ void onNotificationClear(String pkg, int userId, String key,
int dismissalSurface, int dismissalSentiment, in NotificationVisibility nv);
void onNotificationVisibilityChanged( in NotificationVisibility[] newlyVisibleKeys,
in NotificationVisibility[] noLongerVisibleKeys);
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index f7d440d..95e0a3b 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -94,6 +94,6 @@
void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo);
void notifyPhysicalChannelConfigForSubscriber(in int subId,
in List<PhysicalChannelConfig> configs);
- void notifyDataEnabled(boolean enabled, int reason);
+ void notifyDataEnabled(in int phoneId, int subId, boolean enabled, int reason);
void notifyAllowedNetworkTypesChanged(in int phoneId, in int subId, in Map allowedNetworkTypeList);
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 8982519..b40ffb0 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -24,6 +24,7 @@
import android.content.ComponentName;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
+import android.hardware.SensorPrivacyManager;
import android.os.Build;
import android.os.CarrierAssociatedAppEntry;
import android.os.Environment;
@@ -1234,10 +1235,10 @@
addFeature(PackageManager.FEATURE_RAM_NORMAL, 0);
}
- if (IncrementalManager.isFeatureEnabled()) {
+ final int incrementalVersion = IncrementalManager.getVersion();
+ if (incrementalVersion > 0) {
addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY, 0);
- addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY_VERSION,
- IncrementalManager.isV2Available() ? 2 : 1);
+ addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY_VERSION, incrementalVersion);
}
if (PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT) {
@@ -1252,6 +1253,14 @@
addFeature(PackageManager.FEATURE_CROSS_LAYER_BLUR, 0);
}
+ if (SensorPrivacyManager.USE_MICROPHONE_TOGGLE) {
+ addFeature(PackageManager.FEATURE_MICROPHONE_TOGGLE, 0);
+ }
+
+ if (SensorPrivacyManager.USE_CAMERA_TOGGLE) {
+ addFeature(PackageManager.FEATURE_CAMERA_TOGGLE, 0);
+ }
+
for (String featureName : mUnavailableFeatures) {
removeFeature(featureName);
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index dd1a594..b485f0f 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -121,6 +121,7 @@
"android_view_PointerIcon.cpp",
"android_view_Surface.cpp",
"android_view_SurfaceControl.cpp",
+ "android_view_SurfaceControlFpsListener.cpp",
"android_graphics_BLASTBufferQueue.cpp",
"android_view_SurfaceSession.cpp",
"android_view_TextureView.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 1751be0..dc77bba 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -120,6 +120,7 @@
extern int register_android_view_InputWindowHandle(JNIEnv* env);
extern int register_android_view_Surface(JNIEnv* env);
extern int register_android_view_SurfaceControl(JNIEnv* env);
+extern int register_android_view_SurfaceControlFpsListener(JNIEnv* env);
extern int register_android_view_SurfaceSession(JNIEnv* env);
extern int register_android_view_CompositionSamplingListener(JNIEnv* env);
extern int register_android_view_TextureView(JNIEnv* env);
@@ -1488,6 +1489,7 @@
REG_JNI(register_android_view_InputWindowHandle),
REG_JNI(register_android_view_Surface),
REG_JNI(register_android_view_SurfaceControl),
+ REG_JNI(register_android_view_SurfaceControlFpsListener),
REG_JNI(register_android_view_SurfaceSession),
REG_JNI(register_android_view_CompositionSamplingListener),
REG_JNI(register_android_view_TextureView),
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index cbf4481..451ea93 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -27,7 +27,6 @@
#include <android-base/chrono_utils.h>
#include <android/graphics/region.h>
#include <android/gui/BnScreenCaptureListener.h>
-#include <android/hardware/display/IDeviceProductInfoConstants.h>
#include <android/os/IInputConstants.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
@@ -1023,24 +1022,16 @@
} else {
LOG_FATAL("Unknown alternative for variant DeviceProductInfo::ManufactureOrModelDate");
}
- jint connectionToSinkType;
- // Relative address maps to HDMI physical address. All addresses are 4 digits long allowing
- // for a 5–device-deep hierarchy. For more information, refer:
- // Section 8.7 - Physical Address of HDMI Specification Version 1.3a
- using android::hardware::display::IDeviceProductInfoConstants;
- if (info->relativeAddress.size() != 4) {
- connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_UNKNOWN;
- } else if (info->relativeAddress[0] == 0) {
- connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_BUILT_IN;
- } else if (info->relativeAddress[1] == 0) {
- connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_DIRECT;
- } else {
- connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_TRANSITIVE;
+ auto relativeAddress = env->NewIntArray(info->relativeAddress.size());
+ auto relativeAddressData = env->GetIntArrayElements(relativeAddress, nullptr);
+ for (int i = 0; i < info->relativeAddress.size(); i++) {
+ relativeAddressData[i] = info->relativeAddress[i];
}
+ env->ReleaseIntArrayElements(relativeAddress, relativeAddressData, 0);
return env->NewObject(gDeviceProductInfoClassInfo.clazz, gDeviceProductInfoClassInfo.ctor, name,
manufacturerPnpId, productId, modelYear, manufactureDate,
- connectionToSinkType);
+ relativeAddress);
}
static jobject nativeGetStaticDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
@@ -1979,7 +1970,7 @@
"Ljava/lang/String;"
"Ljava/lang/Integer;"
"Landroid/hardware/display/DeviceProductInfo$ManufactureDate;"
- "I)V");
+ "[I)V");
jclass deviceProductInfoManufactureDateClazz =
FindClassOrDie(env, "android/hardware/display/DeviceProductInfo$ManufactureDate");
diff --git a/core/jni/android_view_SurfaceControlFpsListener.cpp b/core/jni/android_view_SurfaceControlFpsListener.cpp
new file mode 100644
index 0000000..6fa12e5
--- /dev/null
+++ b/core/jni/android_view_SurfaceControlFpsListener.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceControlFpsListener"
+
+#include <android/gui/BnFpsListener.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <gui/ISurfaceComposer.h>
+#include <gui/SurfaceComposerClient.h>
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+#include "android_util_Binder.h"
+#include "core_jni_helpers.h"
+
+namespace android {
+
+namespace {
+
+struct {
+ jclass mClass;
+ jmethodID mDispatchOnFpsReported;
+} gListenerClassInfo;
+
+struct SurfaceControlFpsListener : public gui::BnFpsListener {
+ SurfaceControlFpsListener(JNIEnv* env, jobject listener)
+ : mListener(env->NewWeakGlobalRef(listener)) {}
+
+ binder::Status onFpsReported(float fps) override {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onFpsReported.");
+
+ jobject listener = env->NewGlobalRef(mListener);
+ if (listener == NULL) {
+ // Weak reference went out of scope
+ return binder::Status::ok();
+ }
+ env->CallStaticVoidMethod(gListenerClassInfo.mClass,
+ gListenerClassInfo.mDispatchOnFpsReported, listener,
+ static_cast<jfloat>(fps));
+ env->DeleteGlobalRef(listener);
+
+ if (env->ExceptionCheck()) {
+ ALOGE("SurfaceControlFpsListener.onFpsReported() failed.");
+ LOGE_EX(env);
+ env->ExceptionClear();
+ }
+ return binder::Status::ok();
+ }
+
+protected:
+ virtual ~SurfaceControlFpsListener() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ env->DeleteWeakGlobalRef(mListener);
+ }
+
+private:
+ jweak mListener;
+};
+
+jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) {
+ SurfaceControlFpsListener* listener = new SurfaceControlFpsListener(env, obj);
+ listener->incStrong((void*)nativeCreate);
+ return reinterpret_cast<jlong>(listener);
+}
+
+void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
+ SurfaceControlFpsListener* listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
+ listener->decStrong((void*)nativeCreate);
+}
+
+void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr, jlong layerObj) {
+ sp<SurfaceControlFpsListener> listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
+ auto layer = reinterpret_cast<SurfaceControl*>(layerObj);
+ sp<IBinder> layerHandle = layer != nullptr ? layer->getHandle() : nullptr;
+ if (SurfaceComposerClient::addFpsListener(layerHandle, listener) != OK) {
+ constexpr auto error_msg = "Couldn't addFpsListener";
+ ALOGE(error_msg);
+ jniThrowRuntimeException(env, error_msg);
+ }
+}
+
+void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
+ sp<SurfaceControlFpsListener> listener = reinterpret_cast<SurfaceControlFpsListener*>(ptr);
+
+ if (SurfaceComposerClient::removeFpsListener(listener) != OK) {
+ constexpr auto error_msg = "Couldn't removeFpsListener";
+ ALOGE(error_msg);
+ jniThrowRuntimeException(env, error_msg);
+ }
+}
+
+const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ {"nativeCreate", "(Landroid/view/SurfaceControlFpsListener;)J", (void*)nativeCreate},
+ {"nativeDestroy", "(J)V", (void*)nativeDestroy},
+ {"nativeRegister", "(JJ)V", (void*)nativeRegister},
+ {"nativeUnregister", "(J)V", (void*)nativeUnregister}};
+
+} // namespace
+
+int register_android_view_SurfaceControlFpsListener(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env, "android/view/SurfaceControlFpsListener", gMethods,
+ NELEM(gMethods));
+ LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+ jclass clazz = env->FindClass("android/view/SurfaceControlFpsListener");
+ gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
+ gListenerClassInfo.mDispatchOnFpsReported =
+ env->GetStaticMethodID(clazz, "dispatchOnFpsReported",
+ "(Landroid/view/SurfaceControlFpsListener;F)V");
+ return 0;
+}
+
+} // namespace android
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index a1be865c..ec502c3 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -174,10 +174,10 @@
// Use root_display_area instead
optional WindowContainerProto window_container = 1 [deprecated=true];
optional int32 id = 2;
- reserved 3; // stacks
- optional DockedStackDividerControllerProto docked_stack_divider_controller = 4 [deprecated=true];
+ reserved 3; // RootTasks
+ optional DockedTaskDividerControllerProto docked_task_divider_controller = 4 [deprecated=true];
// Will be removed soon.
- optional PinnedStackControllerProto pinned_stack_controller = 5 [deprecated=true];
+ optional PinnedTaskControllerProto pinned_task_controller = 5 [deprecated=true];
/* non app windows */
repeated WindowTokenProto above_app_windows = 6 [deprecated=true];
repeated WindowTokenProto below_app_windows = 7 [deprecated=true];
@@ -256,15 +256,15 @@
optional int32 last_orientation = 5 [(.android.typedef) = "android.content.pm.ActivityInfo.ScreenOrientation"];
}
-/* represents DockedStackDividerController */
-message DockedStackDividerControllerProto {
+/* represents DockedTaskDividerController */
+message DockedTaskDividerControllerProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
optional bool minimized_dock = 1 [deprecated=true];
}
-/* represents PinnedStackController */
-message PinnedStackControllerProto {
+/* represents PinnedTaskController */
+message PinnedTaskControllerProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
optional .android.graphics.RectProto default_bounds = 1 [deprecated=true];
diff --git a/core/res/Android.bp b/core/res/Android.bp
index 4cf9cfb..b988b5a 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -44,11 +44,73 @@
],
}
+genrule {
+ name: "remote-color-resources-compile-public",
+ tools: ["aapt2"],
+ srcs: [
+ "remote_color_resources_res/values/public.xml",
+ ],
+ out: ["values_public.arsc.flat"],
+ cmd: "$(location aapt2) compile $(in) -o $(genDir)",
+}
+
+genrule {
+ name: "remote-color-resources-compile-colors",
+ tools: ["aapt2"],
+ srcs: [
+ "remote_color_resources_res/values/colors.xml",
+ ],
+ out: ["values_colors.arsc.flat"],
+ cmd: "$(location aapt2) compile $(in) -o $(genDir)",
+}
+
+genrule {
+ name: "remote-color-resources-apk",
+ tools: ["aapt2"],
+ // The first input file in the list must be the manifest
+ srcs: [
+ "RemoteThemeColorsAndroidManifest.xml",
+ ":remote-color-resources-compile-public",
+ ":remote-color-resources-compile-colors",
+ ],
+ out: ["remote-color-resources.apk"],
+ cmd: "$(location aapt2) link -o $(out) --manifest $(in)"
+}
+
+genrule {
+ name: "remote-color-resources-arsc",
+ srcs: [":remote-color-resources-apk"],
+ out: ["res/raw/remote_views_color_resources.arsc"],
+ cmd: "mkdir -p $(genDir)/remote-color-resources-arsc && "
+ + "unzip -x $(in) resources.arsc -d $(genDir)/remote-color-resources-arsc && "
+ + "mkdir -p $$(dirname $(out)) && "
+ + "mv $(genDir)/remote-color-resources-arsc/resources.arsc $(out) && "
+ + "echo 'Created $(out)'"
+}
+
+genrule {
+ name: "remote-color-resources-arsc-zip",
+ tools: ["soong_zip"],
+ srcs: [
+ ":remote-color-resources-arsc",
+ "remote_color_resources_res/symbols.xml",
+ ],
+ out: ["remote_views_color_resources.zip"],
+ cmd: "INPUTS=($(in)) && "
+ + "RES_DIR=$$(dirname $$(dirname $${INPUTS[0]})) && "
+ + "mkdir -p $$RES_DIR/values && "
+ + "cp $${INPUTS[1]} $$RES_DIR/values && "
+ + "$(location soong_zip) -o $(out) -C $$RES_DIR -D $$RES_DIR && "
+ + "cp $(out) ."
+}
+
android_app {
name: "framework-res",
sdk_version: "core_platform",
certificate: "platform",
+ srcs: [":remote-color-resources-arsc"],
+
// Disable dexpreopt and verify_uses_libraries check as the app
// contains no Java code to be dexpreopted.
enforce_uses_libs: false,
@@ -72,6 +134,10 @@
"--auto-add-overlay",
],
+ resource_zips: [
+ ":remote-color-resources-arsc-zip",
+ ],
+
// Create package-export.apk, which other packages can use to get
// PRODUCT-agnostic resource data like IDs and type definitions.
export_package_resources: true,
@@ -96,6 +162,7 @@
srcs: [
"assets/**/*",
"res/**/*",
+ ":remote-color-resources-arsc",
],
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5dd8580..a89043d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2641,6 +2641,16 @@
android:label="@string/permlab_manageProfileAndDeviceOwners"
android:description="@string/permdesc_manageProfileAndDeviceOwners" />
+ <!-- @TestApi @hide Allows an application to reset the record of previous system update freeze
+ periods. -->
+ <permission android:name="android.permission.CLEAR_FREEZE_PERIOD"
+ android:protectionLevel="signature" />
+
+ <!-- @TestApi @hide Allows an application to force available DevicePolicyManager logs to
+ DPC. -->
+ <permission android:name="android.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to get full detailed information about
recently running tasks, with full fidelity to the real state.
@hide -->
@@ -5421,6 +5431,12 @@
@hide -->
<permission android:name="android.permission.MANAGE_SENSOR_PRIVACY"
android:protectionLevel="signature" />
+
+ <!-- @SystemApi Allows sensor privacy changes to be observed.
+ @hide -->
+ <permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY"
+ android:protectionLevel="signature|installer" />
+
<!-- @SystemApi Permission that protects the {@link Intent#ACTION_REVIEW_ACCESSIBILITY_SERVICES}
intent.
@hide -->
diff --git a/core/res/RemoteThemeColorsAndroidManifest.xml b/core/res/RemoteThemeColorsAndroidManifest.xml
new file mode 100644
index 0000000..11970fd
--- /dev/null
+++ b/core/res/RemoteThemeColorsAndroidManifest.xml
@@ -0,0 +1,5 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+<application/>
+</manifest>
+
diff --git a/core/res/remote_color_resources_res/symbols.xml b/core/res/remote_color_resources_res/symbols.xml
new file mode 100644
index 0000000..82d5e3e
--- /dev/null
+++ b/core/res/remote_color_resources_res/symbols.xml
@@ -0,0 +1,4 @@
+<resources>
+ <!-- ARSC file used to overlay local colors when rendering a RemoteViews -->
+ <java-symbol type="raw" name="remote_views_color_resources" />
+</resources>
diff --git a/core/res/remote_color_resources_res/values/colors.xml b/core/res/remote_color_resources_res/values/colors.xml
new file mode 100644
index 0000000..295f16e
--- /dev/null
+++ b/core/res/remote_color_resources_res/values/colors.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Note: the values of the colors doesn't really matter (they will always be overwritten before used), but they help a lot debugging, to find out which color is where in the ARSC file. -->
+ <color name="system_primary_0">#01010101</color>
+ <color name="system_primary_50">#02020202</color>
+ <color name="system_primary_100">#03030303</color>
+ <color name="system_primary_200">#04040404</color>
+ <color name="system_primary_300">#05050505</color>
+ <color name="system_primary_400">#06060606</color>
+ <color name="system_primary_500">#07070707</color>
+ <color name="system_primary_600">#08080808</color>
+ <color name="system_primary_700">#09090909</color>
+ <color name="system_primary_800">#0a0a0a0a</color>
+ <color name="system_primary_900">#0b0b0b0b</color>
+ <color name="system_primary_1000">#0c0c0c0c</color>
+ <color name="system_secondary_0">#10101010</color>
+ <color name="system_secondary_50">#20202020</color>
+ <color name="system_secondary_100">#30303030</color>
+ <color name="system_secondary_200">#40404040</color>
+ <color name="system_secondary_300">#50505050</color>
+ <color name="system_secondary_400">#60606060</color>
+ <color name="system_secondary_500">#70707070</color>
+ <color name="system_secondary_600">#80808080</color>
+ <color name="system_secondary_700">#90909090</color>
+ <color name="system_secondary_800">#a0a0a0a0</color>
+ <color name="system_secondary_900">#b0b0b0b0</color>
+ <color name="system_secondary_1000">#c0c0c0c0</color>
+ <color name="system_neutral_0">#1f1f1f1f</color>
+ <color name="system_neutral_50">#2f2f2f2f</color>
+ <color name="system_neutral_100">#3f3f3f3f</color>
+ <color name="system_neutral_200">#4f4f4f4f</color>
+ <color name="system_neutral_300">#5f5f5f5f</color>
+ <color name="system_neutral_400">#6f6f6f6f</color>
+ <color name="system_neutral_500">#7f7f7f7f</color>
+ <color name="system_neutral_600">#8f8f8f8f</color>
+ <color name="system_neutral_700">#9f9f9f9f</color>
+ <color name="system_neutral_800">#afafafaf</color>
+ <color name="system_neutral_900">#bfbfbfbf</color>
+ <color name="system_neutral_1000">#cfcfcfcf</color>
+</resources>
diff --git a/core/res/remote_color_resources_res/values/public.xml b/core/res/remote_color_resources_res/values/public.xml
new file mode 100644
index 0000000..e628f09
--- /dev/null
+++ b/core/res/remote_color_resources_res/values/public.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <public-group type="color" first-id="0x0106001d">
+ <public name="system_primary_0" />
+ <public name="system_primary_50" />
+ <public name="system_primary_100" />
+ <public name="system_primary_200" />
+ <public name="system_primary_300" />
+ <public name="system_primary_400" />
+ <public name="system_primary_500" />
+ <public name="system_primary_600" />
+ <public name="system_primary_700" />
+ <public name="system_primary_800" />
+ <public name="system_primary_900" />
+ <public name="system_primary_1000" />
+ <public name="system_secondary_0" />
+ <public name="system_secondary_50" />
+ <public name="system_secondary_100" />
+ <public name="system_secondary_200" />
+ <public name="system_secondary_300" />
+ <public name="system_secondary_400" />
+ <public name="system_secondary_500" />
+ <public name="system_secondary_600" />
+ <public name="system_secondary_700" />
+ <public name="system_secondary_800" />
+ <public name="system_secondary_900" />
+ <public name="system_secondary_1000" />
+ <public name="system_neutral_0" />
+ <public name="system_neutral_50" />
+ <public name="system_neutral_100" />
+ <public name="system_neutral_200" />
+ <public name="system_neutral_300" />
+ <public name="system_neutral_400" />
+ <public name="system_neutral_500" />
+ <public name="system_neutral_600" />
+ <public name="system_neutral_700" />
+ <public name="system_neutral_800" />
+ <public name="system_neutral_900" />
+ <public name="system_neutral_1000" />
+ </public-group>
+</resources>
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 6211463..1de1d04 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -17,8 +17,8 @@
<NotificationHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/notification_header"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/notification_header_solo_height"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/notification_header_height"
android:layout_marginBottom="@dimen/notification_header_margin_bottom"
android:clipChildren="false"
android:gravity="center_vertical"
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index de537b2..2d1c342 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -38,11 +38,7 @@
android:layout_gravity="top"
>
- <include
- layout="@layout/notification_template_header"
- android:layout_width="match_parent"
- android:layout_height="@dimen/notification_header_big_height"
- />
+ <include layout="@layout/notification_template_header" />
<LinearLayout
android:id="@+id/notification_main_column"
diff --git a/core/res/res/layout/notification_template_material_big_media.xml b/core/res/res/layout/notification_template_material_big_media.xml
index 696cb65..bdd4430 100644
--- a/core/res/res/layout/notification_template_material_big_media.xml
+++ b/core/res/res/layout/notification_template_material_big_media.xml
@@ -36,7 +36,6 @@
layout="@layout/notification_template_header"
android:layout_width="match_parent"
android:layout_height="@dimen/media_notification_header_height"
- android:layout_gravity="start"
/>
<LinearLayout
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index e1b7bc4..6f3c77f 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -23,11 +23,7 @@
android:clipChildren="false"
>
- <include
- layout="@layout/notification_template_header"
- android:layout_width="match_parent"
- android:layout_height="@dimen/notification_header_big_height"
- />
+ <include layout="@layout/notification_template_header" />
<include layout="@layout/notification_template_right_icon" />
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 2452a32..2954ba2 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -23,11 +23,7 @@
android:tag="bigText"
>
- <include
- layout="@layout/notification_template_header"
- android:layout_width="match_parent"
- android:layout_height="@dimen/notification_header_big_height"
- />
+ <include layout="@layout/notification_template_header" />
<com.android.internal.widget.RemeasuringLinearLayout
android:id="@+id/notification_action_list_margin_target"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 7daccd2..baffdd5 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -32,7 +32,8 @@
/>
<include layout="@layout/notification_template_header"
android:layout_width="match_parent"
- android:layout_height="@dimen/media_notification_header_height" />
+ android:layout_height="@dimen/media_notification_header_height"
+ />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/core/res/res/values-night/values.xml b/core/res/res/values-night/values.xml
index 952cdd0..b1bcf72 100644
--- a/core/res/res/values-night/values.xml
+++ b/core/res/res/values-night/values.xml
@@ -30,7 +30,7 @@
<style name="Theme.DeviceDefault.QuickSettings.Dialog" parent="Theme.DeviceDefault.Dialog" />
<style name="TextAppearance.Material.Notification">
- <item name="textColor">?attr/textColorPrimary</item>
+ <item name="textColor">@color/notification_secondary_text_color_dark</item>
<item name="textSize">@dimen/notification_text_size</item>
</style>
</resources>
\ No newline at end of file
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0ae6a76..45e11ba 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1893,6 +1893,11 @@
<!-- User data will remain unchanged during rollback. -->
<enum name="retain" value="2" />
</attr>
+
+ <!-- Applications can set this attribute to an xml resource within their app where they
+ specified the rules determining which files and directories can be copied from the device
+ as part of backup or transfer operations. -->
+ <attr name="dataExtractionRules" format="reference"/>
</declare-styleable>
<!-- An attribution is a logical part of an app and is identified by a tag.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9a917b7..592a3a1 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1173,6 +1173,9 @@
<!-- Default value for LED off time when the battery is low on charge in miliseconds -->
<integer name="config_notificationsBatteryLedOff">2875</integer>
+ <!-- If true, only colorized CallStyle notifications will apply custom colors -->
+ <bool name="config_callNotificationActionColorsRequireColorized">true</bool>
+
<!-- Number of notifications to keep in the notification service historical archive -->
<integer name="config_notificationServiceArchiveSize">100</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 1ca5498..695a831 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -271,11 +271,8 @@
<!-- The top margin before the notification progress bar. -->
<dimen name="notification_progress_margin_top">8dp</dimen>
- <!-- height of the notification header when the notification is alone (minimized / groups) -->
- <dimen name="notification_header_solo_height">48dp</dimen>
-
- <!-- height of the notification header when in a "big" layout -->
- <dimen name="notification_header_big_height">56dp</dimen>
+ <!-- height of the notification header -->
+ <dimen name="notification_header_height">56dp</dimen>
<!-- The height of the background for a notification header on a group -->
<dimen name="notification_header_background_height">49.5dp</dimen>
@@ -365,7 +362,7 @@
<dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen>
<!-- The absolute height for the header in a media notification. -->
- <dimen name="media_notification_header_height">@dimen/notification_header_big_height</dimen>
+ <dimen name="media_notification_header_height">@dimen/notification_header_height</dimen>
<!-- The margin of the content to an image-->
<dimen name="notification_content_image_margin_end">8dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4732e5f..9b2573f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3084,6 +3084,7 @@
<public name="hand_minuteTintMode"/>
<public name="hand_secondTint"/>
<public name="hand_secondTintMode"/>
+ <public name="dataExtractionRules"/>
</public-group>
<public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e73d6e3..7ad05de 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2286,6 +2286,7 @@
<java-symbol type="string" name="config_wifi_tether_enable" />
<java-symbol type="bool" name="config_intrusiveNotificationLed" />
<java-symbol type="bool" name="config_notificationBadging" />
+ <java-symbol type="bool" name="config_callNotificationActionColorsRequireColorized" />
<java-symbol type="dimen" name="preference_fragment_padding_bottom" />
<java-symbol type="dimen" name="preference_fragment_padding_side" />
<java-symbol type="drawable" name="expander_ic_maximized" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index e7e049da..16d720b 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -238,6 +238,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -271,6 +273,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -306,6 +310,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -340,6 +346,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -417,6 +425,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -449,6 +459,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -482,6 +494,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -531,6 +545,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -565,6 +581,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -597,6 +615,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -631,6 +651,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -664,6 +686,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -697,6 +721,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -730,6 +756,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -763,6 +791,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -800,6 +830,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -834,6 +866,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -865,6 +899,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -1069,6 +1105,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1101,6 +1139,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1134,6 +1174,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1169,6 +1211,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1203,6 +1247,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1281,6 +1327,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1316,6 +1364,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1352,6 +1402,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1426,6 +1478,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1463,6 +1517,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1498,6 +1554,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1532,6 +1590,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1565,6 +1625,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1598,6 +1660,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1629,6 +1693,8 @@
<item name="colorPrimaryDark">@color/primary_dark_device_default_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1750,6 +1816,8 @@
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_dark</item>
<item name="colorError">@color/error_color_device_default_dark</item>
+ <item name="colorBackground">@color/background_device_default_dark</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_dark</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_dark</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_dark</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_dark</item>
@@ -1782,6 +1850,8 @@
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1824,6 +1894,8 @@
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
@@ -1859,6 +1931,8 @@
<item name="colorSecondary">@color/secondary_device_default_settings</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
+ <item name="colorBackground">@color/background_device_default_light</item>
+ <item name="colorBackgroundFloating">@color/background_floating_device_default_light</item>
<item name="textColorPrimary">@color/text_color_primary_device_default_light</item>
<item name="textColorSecondary">@color/text_color_secondary_device_default_light</item>
<item name="textColorTertiary">@color/text_color_tertiary_device_default_light</item>
diff --git a/core/tests/GameManagerTests/Android.bp b/core/tests/GameManagerTests/Android.bp
index e178776..2789e9f 100644
--- a/core/tests/GameManagerTests/Android.bp
+++ b/core/tests/GameManagerTests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "FrameworksCoreGameManagerTests",
// Include all test java files
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp b/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp
index ade97b8..1c0ea83 100644
--- a/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "BatteryStatsLoadTests",
srcs: ["src/**/*.java"],
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/Android.bp b/core/tests/batterystatstests/BatteryStatsViewer/Android.bp
index 1e0498b..c2e7d81 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/Android.bp
+++ b/core/tests/batterystatstests/BatteryStatsViewer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "BatteryStatsViewer",
srcs: ["src/**/*.java"],
diff --git a/core/tests/coretests/src/android/util/RotationUtilsTest.java b/core/tests/coretests/src/android/util/RotationUtilsTest.java
new file mode 100644
index 0000000..5dbe03e
--- /dev/null
+++ b/core/tests/coretests/src/android/util/RotationUtilsTest.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 android.util;
+
+import static android.util.RotationUtils.rotateBounds;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import static org.junit.Assert.assertEquals;
+
+import android.graphics.Rect;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link RotationUtils}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksCoreTests:RotationUtilsTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RotationUtilsTest {
+
+ @Test
+ public void testRotateBounds() {
+ Rect testParent = new Rect(0, 0, 1000, 600);
+ Rect testInner = new Rect(40, 20, 120, 80);
+
+ Rect testResult = new Rect(testInner);
+ rotateBounds(testResult, testParent, ROTATION_90);
+ assertEquals(new Rect(20, 880, 80, 960), testResult);
+
+ testResult.set(testInner);
+ rotateBounds(testResult, testParent, ROTATION_180);
+ assertEquals(new Rect(880, 520, 960, 580), testResult);
+
+ testResult.set(testInner);
+ rotateBounds(testResult, testParent, ROTATION_270);
+ assertEquals(new Rect(520, 40, 580, 120), testResult);
+ }
+}
diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS
index 5031ff9..80165f0 100644
--- a/core/tests/coretests/src/android/view/OWNERS
+++ b/core/tests/coretests/src/android/view/OWNERS
@@ -1,7 +1,7 @@
# Input
-per-file *MotionEventTest.* = michaelwr@google.com, svv@google.com
-per-file *KeyEventTest.* = michaelwr@google.com, svv@google.com
-per-file VelocityTest.java = michaelwr@google.com, svv@google.com
+per-file *MotionEventTest.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file *KeyEventTest.* = file:/services/core/java/com/android/server/input/OWNERS
+per-file VelocityTest.java = file:/services/core/java/com/android/server/input/OWNERS
# WindowManager
per-file *Display* = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/android/view/SoundEffectConstantsTest.java b/core/tests/coretests/src/android/view/SoundEffectConstantsTest.java
new file mode 100644
index 0000000..45ffb122
--- /dev/null
+++ b/core/tests/coretests/src/android/view/SoundEffectConstantsTest.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 android.view;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SoundEffectConstants}
+ *
+ * Build/Install/Run:
+ * atest FrameworksCoreTests:SoundEffectConstantsTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SoundEffectConstantsTest {
+
+ @Test
+ public void testIsNavigationRepeat() {
+ assertTrue(SoundEffectConstants.isNavigationRepeat(
+ SoundEffectConstants.NAVIGATION_REPEAT_RIGHT));
+ assertTrue(SoundEffectConstants.isNavigationRepeat(
+ SoundEffectConstants.NAVIGATION_REPEAT_LEFT));
+ assertTrue(
+ SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_REPEAT_UP));
+ assertTrue(SoundEffectConstants.isNavigationRepeat(
+ SoundEffectConstants.NAVIGATION_REPEAT_DOWN));
+ assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_RIGHT));
+ assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_LEFT));
+ assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_UP));
+ assertFalse(SoundEffectConstants.isNavigationRepeat(SoundEffectConstants.NAVIGATION_DOWN));
+ assertFalse(SoundEffectConstants.isNavigationRepeat(-1));
+ }
+}
diff --git a/core/tests/coretests/src/android/view/SurfaceControlFpsListenerTest.java b/core/tests/coretests/src/android/view/SurfaceControlFpsListenerTest.java
new file mode 100644
index 0000000..36104cf
--- /dev/null
+++ b/core/tests/coretests/src/android/view/SurfaceControlFpsListenerTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class SurfaceControlFpsListenerTest {
+
+ @Test
+ public void registersAndUnregisters() {
+
+ SurfaceControlFpsListener listener = new SurfaceControlFpsListener() {
+ @Override
+ public void onFpsReported(float fps) {
+ // Ignore
+ }
+ };
+
+ listener.register(new SurfaceControl());
+
+ listener.unregister();
+ }
+}
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 10aaf31..9cb7876 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -105,7 +105,8 @@
mTracker = Mockito.spy(
new FrameTracker(session, handler, mRenderer, mViewRootWrapper,
mSurfaceControlWrapper, mChoreographer, mWrapper,
- /*traceThresholdMissedFrames=*/ 1, /*traceThresholdFrameTimeMillis=*/ -1));
+ /*traceThresholdMissedFrames=*/ 1, /*traceThresholdFrameTimeMillis=*/ -1,
+ null));
doNothing().when(mTracker).triggerPerfetto();
}
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 c4c475b..8f4948c 100644
--- a/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/InteractionJankMonitorTest.java
@@ -96,7 +96,7 @@
new ViewRootWrapper(mView.getViewRootImpl()), new SurfaceControlWrapper(),
mock(FrameTracker.ChoreographerWrapper.class),
new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
- /*traceThresholdFrameTimeMillis=*/ -1));
+ /*traceThresholdFrameTimeMillis=*/ -1, null));
doReturn(tracker).when(monitor).createFrameTracker(any(), any());
// Simulate a trace session and see if begin / end are invoked.
@@ -123,21 +123,12 @@
@Test
public void testCheckInitState() {
InteractionJankMonitor monitor = new InteractionJankMonitor(mWorker);
+ View view = new View(mActivity);
+ assertThat(view.isAttachedToWindow()).isFalse();
- // Should return false if invoking begin / end without init invocation.
- assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isFalse();
+ // Should return false if the view passed in is not attached to window yet.
+ assertThat(monitor.begin(view, 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 {
- assertThat(monitor.begin(mView, CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
- assertThat(monitor.end(CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE)).isTrue();
- } catch (Exception ex) {
- thrown = true;
- } finally {
- assertThat(thrown).isFalse();
- }
}
@Test
@@ -152,7 +143,7 @@
new ViewRootWrapper(mView.getViewRootImpl()), new SurfaceControlWrapper(),
mock(FrameTracker.ChoreographerWrapper.class),
new FrameMetricsWrapper(), /*traceThresholdMissedFrames=*/ 1,
- /*traceThresholdFrameTimeMillis=*/ -1));
+ /*traceThresholdFrameTimeMillis=*/ -1, null));
doReturn(tracker).when(monitor).createFrameTracker(any(), any());
assertThat(monitor.begin(mView, session.getCuj())).isTrue();
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index b819d9e..a1beecc 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -71,6 +71,7 @@
UserPowerCalculatorTest.class,
VideoPowerCalculatorTest.class,
WakelockPowerCalculatorTest.class,
+ WifiPowerCalculatorTest.class,
com.android.internal.power.MeasuredEnergyStatsTest.class
})
diff --git a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
new file mode 100644
index 0000000..e100545
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.NetworkCapabilities;
+import android.net.NetworkStats;
+import android.os.BatteryConsumer;
+import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
+import android.os.WorkSource;
+import android.os.connectivity.WifiActivityEnergyInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class WifiPowerCalculatorTest {
+ private static final double PRECISION = 0.00001;
+
+ private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+
+ @Rule
+ public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
+ .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE, 360.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX, 480.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX, 720.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_ON, 360.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_SCAN, 480.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, 720.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_ACTIVE, 1080.0);
+
+ @Test
+ public void testPowerControllerBasedModel() {
+ BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+ batteryStats.noteNetworkInterfaceForTransports("wifi",
+ new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+
+ NetworkStats networkStats = new NetworkStats(10000, 1)
+ .insertEntry("wifi", APP_UID, 0, 0, 1000, 100, 2000, 20, 100)
+ .insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
+ mStatsRule.setNetworkStats(networkStats);
+
+ WifiActivityEnergyInfo energyInfo = new WifiActivityEnergyInfo(10000,
+ WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 1000, 2000, 3000, 4000);
+
+ batteryStats.updateWifiState(energyInfo, 1000, 1000);
+
+ WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
+ mStatsRule.apply(calculator);
+
+ UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
+ assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+ .isEqualTo(1423);
+ assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isWithin(PRECISION).of(0.2214666);
+
+ SystemBatteryConsumer systemConsumer =
+ mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
+ assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+ .isEqualTo(5577);
+ assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isWithin(PRECISION).of(0.645200);
+ }
+
+ @Test
+ public void testTimerBasedModel() {
+ BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+ batteryStats.noteNetworkInterfaceForTransports("wifi",
+ new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+
+ NetworkStats networkStats = new NetworkStats(10000, 1)
+ .insertEntry("wifi", APP_UID, 0, 0, 1000, 100, 2000, 20, 100)
+ .insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
+ mStatsRule.setNetworkStats(networkStats);
+
+ batteryStats.noteWifiScanStartedLocked(APP_UID, 1000, 1000);
+ batteryStats.noteWifiScanStoppedLocked(APP_UID, 2000, 2000);
+ batteryStats.noteWifiRunningLocked(new WorkSource(APP_UID), 3000, 3000);
+ batteryStats.noteWifiStoppedLocked(new WorkSource(APP_UID), 4000, 4000);
+ batteryStats.noteWifiRunningLocked(new WorkSource(Process.WIFI_UID), 1111, 2222);
+ batteryStats.noteWifiStoppedLocked(new WorkSource(Process.WIFI_UID), 3333, 4444);
+
+ // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
+ // on the packet counts.
+ batteryStats.updateWifiState(/* energyInfo */ null, 1000, 1000);
+
+ WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
+ mStatsRule.apply(calculator);
+
+ UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
+ assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+ .isEqualTo(1000);
+ assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isWithin(PRECISION).of(0.8231573);
+
+ SystemBatteryConsumer systemConsumer =
+ mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
+ assertThat(systemConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
+ .isEqualTo(2222);
+ assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isWithin(PRECISION).of(0.8759216);
+ }
+}
diff --git a/core/tests/devicestatetests/Android.bp b/core/tests/devicestatetests/Android.bp
index 409b77b..f7b5932 100644
--- a/core/tests/devicestatetests/Android.bp
+++ b/core/tests/devicestatetests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "FrameworksCoreDeviceStateManagerTests",
// Include all test java files
diff --git a/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp b/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp
index 42421ce..3536c40 100644
--- a/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/overlaid_apex/Android.bp
@@ -50,4 +50,5 @@
key: "com.android.overlaytest.overlaid.key",
apps: ["OverlayRemountedTest_Target"],
installable: false,
+ updatable: false,
}
diff --git a/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp b/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp
index 0b52dcc..f041404 100644
--- a/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp
+++ b/core/tests/overlaytests/remount/test-apps/overlay_apex/Android.bp
@@ -50,4 +50,5 @@
key: "com.android.overlaytest.overlay.key",
apps: ["OverlayRemountedTest_Overlay"],
installable: false,
+ updatable: false,
}
diff --git a/data/etc/car/com.google.android.car.networking.preferenceupdater.xml b/data/etc/car/com.google.android.car.networking.preferenceupdater.xml
index 489ce1b..cdeb8e4 100644
--- a/data/etc/car/com.google.android.car.networking.preferenceupdater.xml
+++ b/data/etc/car/com.google.android.car.networking.preferenceupdater.xml
@@ -16,12 +16,21 @@
-->
<permissions>
<privapp-permissions package="com.google.android.car.networking.preferenceupdater">
- <permission name="android.permission.ACCESS_NETWORK_STATE"/>
+ <permission name="android.permission.ACCESS_NETWORK_STATE" />
<permission name="android.permission.ACCESS_WIFI_STATE"/>
<permission name="android.permission.ACTIVITY_EMBEDDING"/>
+ <permission name="android.permission.CHANGE_NETWORK_STATE" />
+ <permission name="android.permission.CONNECTIVITY_INTERNAL" />
+ <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+ <permission name="android.permission.CONTROL_OEM_PAID_NETWORK_PREFERNCE" />
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
- <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+ <permission name="android.permission.INTERNET" />
<permission name="android.permission.LOCATION_HARDWARE"/>
+ <permission name="android.permission.PACKAGE_USAGE_STATS" />
+ <permission name="android.permission.RECEIVE_BOOT_COMPLETED" />
+ <permission name="android.permission.WAKE_LOCK" />
+ <permission name="android.permission.WRITE_SETTINGS" />
+ <permission name="android.car.permission.CAR_DRIVING_STATE" />
</privapp-permissions>
</permissions>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 2db4c5d..4f188cc 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -223,7 +223,7 @@
<alias name="sans-serif-condensed-medium" to="sans-serif-condensed" weight="500" />
<family name="serif">
- <font weight="400" style="normal">NotoSerif-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSerif.ttf</font>
<font weight="700" style="normal">NotoSerif-Bold.ttf</font>
<font weight="400" style="italic">NotoSerif-Italic.ttf</font>
<font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
@@ -275,144 +275,144 @@
<!-- fallback fonts -->
<family lang="und-Arab" variant="elegant">
- <font weight="400" style="normal">NotoNaskhArabic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoNaskhArabic.ttf</font>
<font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
</family>
<family lang="und-Arab" variant="compact">
- <font weight="400" style="normal">NotoNaskhArabicUI-Regular.ttf</font>
+ <font weight="400" style="normal">NotoNaskhArabicUI.ttf</font>
<font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
</family>
<family lang="und-Ethi">
- <font weight="400" style="normal">NotoSansEthiopic-VF.ttf
+ <font weight="400" style="normal">NotoSansEthiopic-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansEthiopic-VF.ttf
+ <font weight="500" style="normal">NotoSansEthiopic-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansEthiopic-VF.ttf
+ <font weight="600" style="normal">NotoSansEthiopic-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansEthiopic-VF.ttf
+ <font weight="700" style="normal">NotoSansEthiopic-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifEthiopic-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifEthiopic-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifEthiopic-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifEthiopic-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifEthiopic-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifEthiopic-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifEthiopic-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifEthiopic-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Hebr">
- <font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansHebrew.ttf</font>
<font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
<font weight="400" style="normal" fallbackFor="serif">NotoSerifHebrew-Regular.ttf</font>
<font weight="700" style="normal" fallbackFor="serif">NotoSerifHebrew-Bold.ttf</font>
</family>
<family lang="und-Thai" variant="elegant">
- <font weight="400" style="normal">NotoSansThai-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansThai.ttf</font>
<font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifThai-Regular.ttf</font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifThai.ttf</font>
<font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
</family>
<family lang="und-Thai" variant="compact">
- <font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansThaiUI.ttf</font>
<font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
</family>
<family lang="und-Armn">
- <font weight="400" style="normal">NotoSansArmenian-VF.ttf
+ <font weight="400" style="normal">NotoSansArmenian-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansArmenian-VF.ttf
+ <font weight="500" style="normal">NotoSansArmenian-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansArmenian-VF.ttf
+ <font weight="600" style="normal">NotoSansArmenian-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansArmenian-VF.ttf
+ <font weight="700" style="normal">NotoSansArmenian-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifArmenian-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifArmenian-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Geor,und-Geok">
- <font weight="400" style="normal">NotoSansGeorgian-VF.ttf
+ <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansGeorgian-VF.ttf
+ <font weight="500" style="normal">NotoSansGeorgian-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansGeorgian-VF.ttf
+ <font weight="600" style="normal">NotoSansGeorgian-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansGeorgian-VF.ttf
+ <font weight="700" style="normal">NotoSansGeorgian-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifGeorgian-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifGeorgian-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifGeorgian-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifGeorgian-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifGeorgian-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifGeorgian-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifGeorgian-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifGeorgian-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Deva" variant="elegant">
- <font weight="400" style="normal">NotoSansDevanagari-VF.ttf
+ <font weight="400" style="normal">NotoSansDevanagari-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansDevanagari-VF.ttf
+ <font weight="500" style="normal">NotoSansDevanagari-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansDevanagari-VF.ttf
+ <font weight="600" style="normal">NotoSansDevanagari-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansDevanagari-VF.ttf
+ <font weight="700" style="normal">NotoSansDevanagari-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Deva" variant="compact">
- <font weight="400" style="normal">NotoSansDevanagariUI-VF.ttf
+ <font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansDevanagariUI-VF.ttf
+ <font weight="500" style="normal">NotoSansDevanagariUI-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansDevanagariUI-VF.ttf
+ <font weight="600" style="normal">NotoSansDevanagariUI-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansDevanagariUI-VF.ttf
+ <font weight="700" style="normal">NotoSansDevanagariUI-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
@@ -421,347 +421,347 @@
danda characters.
-->
<family lang="und-Gujr" variant="elegant">
- <font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansGujarati.ttf</font>
<font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Gujr" variant="compact">
- <font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansGujaratiUI.ttf</font>
<font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
</family>
<family lang="und-Guru" variant="elegant">
- <font weight="400" style="normal">NotoSansGurmukhi-VF.ttf
+ <font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansGurmukhi-VF.ttf
+ <font weight="500" style="normal">NotoSansGurmukhi-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansGurmukhi-VF.ttf
+ <font weight="600" style="normal">NotoSansGurmukhi-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansGurmukhi-VF.ttf
+ <font weight="700" style="normal">NotoSansGurmukhi-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Guru" variant="compact">
- <font weight="400" style="normal">NotoSansGurmukhiUI-VF.ttf
+ <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansGurmukhiUI-VF.ttf
+ <font weight="500" style="normal">NotoSansGurmukhiUI-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansGurmukhiUI-VF.ttf
+ <font weight="600" style="normal">NotoSansGurmukhiUI-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansGurmukhiUI-VF.ttf
+ <font weight="700" style="normal">NotoSansGurmukhiUI-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Taml" variant="elegant">
- <font weight="400" style="normal">NotoSansTamil-VF.ttf
+ <font weight="400" style="normal">NotoSansTamil-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansTamil-VF.ttf
+ <font weight="500" style="normal">NotoSansTamil-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansTamil-VF.ttf
+ <font weight="600" style="normal">NotoSansTamil-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansTamil-VF.ttf
+ <font weight="700" style="normal">NotoSansTamil-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Taml" variant="compact">
- <font weight="400" style="normal">NotoSansTamilUI-VF.ttf
+ <font weight="400" style="normal">NotoSansTamilUI-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansTamilUI-VF.ttf
+ <font weight="500" style="normal">NotoSansTamilUI-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansTamilUI-VF.ttf
+ <font weight="600" style="normal">NotoSansTamilUI-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansTamilUI-VF.ttf
+ <font weight="700" style="normal">NotoSansTamilUI-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Mlym" variant="elegant">
- <font weight="400" style="normal">NotoSansMalayalam-VF.ttf
+ <font weight="400" style="normal">NotoSansMalayalam-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansMalayalam-VF.ttf
+ <font weight="500" style="normal">NotoSansMalayalam-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansMalayalam-VF.ttf
+ <font weight="600" style="normal">NotoSansMalayalam-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansMalayalam-VF.ttf
+ <font weight="700" style="normal">NotoSansMalayalam-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Mlym" variant="compact">
- <font weight="400" style="normal">NotoSansMalayalamUI-VF.ttf
+ <font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansMalayalamUI-VF.ttf
+ <font weight="500" style="normal">NotoSansMalayalamUI-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansMalayalamUI-VF.ttf
+ <font weight="600" style="normal">NotoSansMalayalamUI-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansMalayalamUI-VF.ttf
+ <font weight="700" style="normal">NotoSansMalayalamUI-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Beng" variant="elegant">
- <font weight="400" style="normal">NotoSansBengali-VF.ttf
+ <font weight="400" style="normal">NotoSansBengali-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansBengali-VF.ttf
+ <font weight="500" style="normal">NotoSansBengali-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansBengali-VF.ttf
+ <font weight="600" style="normal">NotoSansBengali-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansBengali-VF.ttf
+ <font weight="700" style="normal">NotoSansBengali-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Beng" variant="compact">
- <font weight="400" style="normal">NotoSansBengaliUI-VF.ttf
+ <font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansBengaliUI-VF.ttf
+ <font weight="500" style="normal">NotoSansBengaliUI-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansBengaliUI-VF.ttf
+ <font weight="600" style="normal">NotoSansBengaliUI-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansBengaliUI-VF.ttf
+ <font weight="700" style="normal">NotoSansBengaliUI-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Telu" variant="elegant">
- <font weight="400" style="normal">NotoSansTelugu-VF.ttf
+ <font weight="400" style="normal">NotoSansTelugu-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansTelugu-VF.ttf
+ <font weight="500" style="normal">NotoSansTelugu-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansTelugu-VF.ttf
+ <font weight="600" style="normal">NotoSansTelugu-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansTelugu-VF.ttf
+ <font weight="700" style="normal">NotoSansTelugu-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Telu" variant="compact">
- <font weight="400" style="normal">NotoSansTeluguUI-VF.ttf
+ <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansTeluguUI-VF.ttf
+ <font weight="500" style="normal">NotoSansTeluguUI-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansTeluguUI-VF.ttf
+ <font weight="600" style="normal">NotoSansTeluguUI-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansTeluguUI-VF.ttf
+ <font weight="700" style="normal">NotoSansTeluguUI-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Knda" variant="elegant">
- <font weight="400" style="normal">NotoSansKannada-VF.ttf
+ <font weight="400" style="normal">NotoSansKannada-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansKannada-VF.ttf
+ <font weight="500" style="normal">NotoSansKannada-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansKannada-VF.ttf
+ <font weight="600" style="normal">NotoSansKannada-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansKannada-VF.ttf
+ <font weight="700" style="normal">NotoSansKannada-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Knda" variant="compact">
- <font weight="400" style="normal">NotoSansKannadaUI-VF.ttf
+ <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansKannadaUI-VF.ttf
+ <font weight="500" style="normal">NotoSansKannadaUI-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansKannadaUI-VF.ttf
+ <font weight="600" style="normal">NotoSansKannadaUI-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansKannadaUI-VF.ttf
+ <font weight="700" style="normal">NotoSansKannadaUI-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Orya" variant="elegant">
- <font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOriya.ttf</font>
<font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
</family>
<family lang="und-Orya" variant="compact">
- <font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOriyaUI.ttf</font>
<font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
</family>
<family lang="und-Sinh" variant="elegant">
- <font weight="400" style="normal">NotoSansSinhala-VF.ttf
+ <font weight="400" style="normal">NotoSansSinhala-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansSinhala-VF.ttf
+ <font weight="500" style="normal">NotoSansSinhala-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansSinhala-VF.ttf
+ <font weight="600" style="normal">NotoSansSinhala-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansSinhala-VF.ttf
+ <font weight="700" style="normal">NotoSansSinhala-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Sinh" variant="compact">
- <font weight="400" style="normal">NotoSansSinhalaUI-VF.ttf
+ <font weight="400" style="normal">NotoSansSinhalaUI-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansSinhalaUI-VF.ttf
+ <font weight="500" style="normal">NotoSansSinhalaUI-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansSinhalaUI-VF.ttf
+ <font weight="600" style="normal">NotoSansSinhalaUI-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansSinhalaUI-VF.ttf
+ <font weight="700" style="normal">NotoSansSinhalaUI-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Khmr" variant="elegant">
- <font weight="100" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="100" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="26.0"/>
</font>
- <font weight="200" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="200" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="39.0"/>
</font>
- <font weight="300" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="300" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="58.0"/>
</font>
- <font weight="400" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="400" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="90.0"/>
</font>
- <font weight="500" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="500" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="108.0"/>
</font>
- <font weight="600" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="600" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="128.0"/>
</font>
- <font weight="700" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="700" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="151.0"/>
</font>
- <font weight="800" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="800" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="169.0"/>
</font>
- <font weight="900" style="normal">NotoSansKhmer-VF.ttf
+ <font weight="900" style="normal">NotoSansKhmer-Regular.ttf
<axis tag="wdth" stylevalue="100.0"/>
<axis tag="wght" stylevalue="190.0"/>
</font>
@@ -769,17 +769,17 @@
<font weight="700" style="normal" fallbackFor="serif">NotoSerifKhmer-Bold.otf</font>
</family>
<family lang="und-Khmr" variant="compact">
- <font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansKhmerUI.ttf</font>
<font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
</family>
<family lang="und-Laoo" variant="elegant">
- <font weight="400" style="normal">NotoSansLao-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansLao.ttf</font>
<font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifLao-Regular.ttf</font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifLao.ttf</font>
<font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
</family>
<family lang="und-Laoo" variant="compact">
- <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansLaoUI.ttf</font>
<font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
</family>
<family lang="und-Mymr" variant="elegant">
@@ -795,56 +795,56 @@
<font weight="700" style="normal">NotoSansMyanmarUI-Bold.otf</font>
</family>
<family lang="und-Thaa">
- <font weight="400" style="normal">NotoSansThaana-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansThaana.ttf</font>
<font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
</family>
<family lang="und-Cham">
- <font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansCham.ttf</font>
<font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
</family>
<family lang="und-Ahom">
<font weight="400" style="normal">NotoSansAhom-Regular.otf</font>
</family>
<family lang="und-Adlm">
- <font weight="400" style="normal">NotoSansAdlam-VF.ttf
+ <font weight="400" style="normal">NotoSansAdlam-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansAdlam-VF.ttf
+ <font weight="500" style="normal">NotoSansAdlam-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansAdlam-VF.ttf
+ <font weight="600" style="normal">NotoSansAdlam-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansAdlam-VF.ttf
+ <font weight="700" style="normal">NotoSansAdlam-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Avst">
- <font weight="400" style="normal">NotoSansAvestan-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansAvestan.ttf</font>
</family>
<family lang="und-Bali">
- <font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansBalinese.ttf</font>
</family>
<family lang="und-Bamu">
- <font weight="400" style="normal">NotoSansBamum-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansBamum.ttf</font>
</family>
<family lang="und-Batk">
- <font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansBatak.ttf</font>
</family>
<family lang="und-Brah">
- <font weight="400" style="normal">NotoSansBrahmi-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansBrahmi.ttf</font>
</family>
<family lang="und-Bugi">
- <font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansBuginese.ttf</font>
</family>
<family lang="und-Buhd">
- <font weight="400" style="normal">NotoSansBuhid-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansBuhid.ttf</font>
</family>
<family lang="und-Cans">
- <font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansCanadianAboriginal.ttf</font>
</family>
<family lang="und-Cari">
- <font weight="400" style="normal">NotoSansCarian-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansCarian.ttf</font>
</family>
<family lang="und-Cakm">
<font weight="400" style="normal">NotoSansChakma-Regular.otf</font>
@@ -853,164 +853,164 @@
<font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
</family>
<family lang="und-Copt">
- <font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansCoptic.ttf</font>
</family>
<family lang="und-Xsux">
- <font weight="400" style="normal">NotoSansCuneiform-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansCuneiform.ttf</font>
</family>
<family lang="und-Cprt">
- <font weight="400" style="normal">NotoSansCypriot-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansCypriot.ttf</font>
</family>
<family lang="und-Dsrt">
- <font weight="400" style="normal">NotoSansDeseret-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansDeseret.ttf</font>
</family>
<family lang="und-Egyp">
- <font weight="400" style="normal">NotoSansEgyptianHieroglyphs-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansEgyptianHieroglyphs.ttf</font>
</family>
<family lang="und-Elba">
<font weight="400" style="normal">NotoSansElbasan-Regular.otf</font>
</family>
<family lang="und-Glag">
- <font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansGlagolitic.ttf</font>
</family>
<family lang="und-Goth">
- <font weight="400" style="normal">NotoSansGothic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansGothic.ttf</font>
</family>
<family lang="und-Hano">
- <font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansHanunoo.ttf</font>
</family>
<family lang="und-Armi">
- <font weight="400" style="normal">NotoSansImperialAramaic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansImperialAramaic.ttf</font>
</family>
<family lang="und-Phli">
- <font weight="400" style="normal">NotoSansInscriptionalPahlavi-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansInscriptionalPahlavi.ttf</font>
</family>
<family lang="und-Prti">
- <font weight="400" style="normal">NotoSansInscriptionalParthian-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansInscriptionalParthian.ttf</font>
</family>
<family lang="und-Java">
<font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
</family>
<family lang="und-Kthi">
- <font weight="400" style="normal">NotoSansKaithi-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansKaithi.ttf</font>
</family>
<family lang="und-Kali">
- <font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansKayahLi.ttf</font>
</family>
<family lang="und-Khar">
- <font weight="400" style="normal">NotoSansKharoshthi-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansKharoshthi.ttf</font>
</family>
<family lang="und-Lepc">
- <font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansLepcha.ttf</font>
</family>
<family lang="und-Limb">
- <font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansLimbu.ttf</font>
</family>
<family lang="und-Linb">
- <font weight="400" style="normal">NotoSansLinearB-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansLinearB.ttf</font>
</family>
<family lang="und-Lisu">
- <font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansLisu.ttf</font>
</family>
<family lang="und-Lyci">
- <font weight="400" style="normal">NotoSansLycian-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansLycian.ttf</font>
</family>
<family lang="und-Lydi">
- <font weight="400" style="normal">NotoSansLydian-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansLydian.ttf</font>
</family>
<family lang="und-Mand">
- <font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansMandaic.ttf</font>
</family>
<family lang="und-Mtei">
- <font weight="400" style="normal">NotoSansMeeteiMayek-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansMeeteiMayek.ttf</font>
</family>
<family lang="und-Talu">
- <font weight="400" style="normal">NotoSansNewTaiLue-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansNewTaiLue.ttf</font>
</family>
<family lang="und-Nkoo">
- <font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansNKo.ttf</font>
</family>
<family lang="und-Ogam">
- <font weight="400" style="normal">NotoSansOgham-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOgham.ttf</font>
</family>
<family lang="und-Olck">
- <font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOlChiki.ttf</font>
</family>
<family lang="und-Ital">
- <font weight="400" style="normal">NotoSansOldItalic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOldItalic.ttf</font>
</family>
<family lang="und-Xpeo">
- <font weight="400" style="normal">NotoSansOldPersian-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOldPersian.ttf</font>
</family>
<family lang="und-Sarb">
- <font weight="400" style="normal">NotoSansOldSouthArabian-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOldSouthArabian.ttf</font>
</family>
<family lang="und-Orkh">
- <font weight="400" style="normal">NotoSansOldTurkic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOldTurkic.ttf</font>
</family>
<family lang="und-Osge">
<font weight="400" style="normal">NotoSansOsage-Regular.ttf</font>
</family>
<family lang="und-Osma">
- <font weight="400" style="normal">NotoSansOsmanya-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansOsmanya.ttf</font>
</family>
<family lang="und-Phnx">
- <font weight="400" style="normal">NotoSansPhoenician-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansPhoenician.ttf</font>
</family>
<family lang="und-Rjng">
- <font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansRejang.ttf</font>
</family>
<family lang="und-Runr">
- <font weight="400" style="normal">NotoSansRunic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansRunic.ttf</font>
</family>
<family lang="und-Samr">
- <font weight="400" style="normal">NotoSansSamaritan-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansSamaritan.ttf</font>
</family>
<family lang="und-Saur">
- <font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansSaurashtra.ttf</font>
</family>
<family lang="und-Shaw">
- <font weight="400" style="normal">NotoSansShavian-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansShavian.ttf</font>
</family>
<family lang="und-Sund">
- <font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansSundanese.ttf</font>
</family>
<family lang="und-Sylo">
- <font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansSylotiNagri.ttf</font>
</family>
<!-- Esrangela should precede Eastern and Western Syriac, since it's our default form. -->
<family lang="und-Syre">
- <font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansSyriacEstrangela.ttf</font>
</family>
<family lang="und-Syrn">
- <font weight="400" style="normal">NotoSansSyriacEastern-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansSyriacEastern.ttf</font>
</family>
<family lang="und-Syrj">
- <font weight="400" style="normal">NotoSansSyriacWestern-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansSyriacWestern.ttf</font>
</family>
<family lang="und-Tglg">
- <font weight="400" style="normal">NotoSansTagalog-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansTagalog.ttf</font>
</family>
<family lang="und-Tagb">
- <font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansTagbanwa.ttf</font>
</family>
<family lang="und-Lana">
- <font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansTaiTham.ttf</font>
</family>
<family lang="und-Tavt">
- <font weight="400" style="normal">NotoSansTaiViet-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansTaiViet.ttf</font>
</family>
<family lang="und-Tibt">
- <font weight="400" style="normal">NotoSerifTibetan-VF.ttf
+ <font weight="400" style="normal">NotoSerifTibetan-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSerifTibetan-VF.ttf
+ <font weight="500" style="normal">NotoSerifTibetan-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSerifTibetan-VF.ttf
+ <font weight="600" style="normal">NotoSerifTibetan-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSerifTibetan-VF.ttf
+ <font weight="700" style="normal">NotoSerifTibetan-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
@@ -1018,29 +1018,29 @@
<font weight="400" style="normal">NotoSansTifinagh-Regular.otf</font>
</family>
<family lang="und-Ugar">
- <font weight="400" style="normal">NotoSansUgaritic-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansUgaritic.ttf</font>
</family>
<family lang="und-Vaii">
- <font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansVai.ttf</font>
</family>
<family>
<font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
</family>
<family lang="zh-Hans">
- <font weight="400" style="normal" index="2">NotoSansCJK-Regular.ttc</font>
- <font weight="400" style="normal" index="2" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
+ <font weight="400" style="normal" index="2">NotoSansCJKjp-Regular.otc</font>
+ <font weight="400" style="normal" index="2" fallbackFor="serif">NotoSerifCJKjp-Regular.otc</font>
</family>
<family lang="zh-Hant,zh-Bopo">
- <font weight="400" style="normal" index="3">NotoSansCJK-Regular.ttc</font>
- <font weight="400" style="normal" index="3" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
+ <font weight="400" style="normal" index="3">NotoSansCJKjp-Regular.otc</font>
+ <font weight="400" style="normal" index="3" fallbackFor="serif">NotoSerifCJKjp-Regular.otc</font>
</family>
<family lang="ja">
- <font weight="400" style="normal" index="0">NotoSansCJK-Regular.ttc</font>
- <font weight="400" style="normal" index="0" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
+ <font weight="400" style="normal" index="0">NotoSansCJKjp-Regular.otc</font>
+ <font weight="400" style="normal" index="0" fallbackFor="serif">NotoSerifCJKjp-Regular.otc</font>
</family>
<family lang="ko">
- <font weight="400" style="normal" index="1">NotoSansCJK-Regular.ttc</font>
- <font weight="400" style="normal" index="1" fallbackFor="serif">NotoSerifCJK-Regular.ttc</font>
+ <font weight="400" style="normal" index="1">NotoSansCJKjp-Regular.otc</font>
+ <font weight="400" style="normal" index="1" fallbackFor="serif">NotoSerifCJKjp-Regular.otc</font>
</family>
<family lang="und-Zsye">
<font weight="400" style="normal">NotoColorEmoji.ttf</font>
@@ -1053,16 +1053,16 @@
override the East Asian punctuation for Chinese.
-->
<family lang="und-Tale">
- <font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansTaiLe.ttf</font>
</family>
<family lang="und-Yiii">
- <font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansYi.ttf</font>
</family>
<family lang="und-Mong">
- <font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansMongolian.ttf</font>
</family>
<family lang="und-Phag">
- <font weight="400" style="normal">NotoSansPhagsPa-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansPhagsPa.ttf</font>
</family>
<family lang="und-Hluw">
<font weight="400" style="normal">NotoSansAnatolianHieroglyphs-Regular.otf</font>
@@ -1152,72 +1152,72 @@
<font weight="400" style="normal">NotoSerifDogra-Regular.ttf</font>
</family>
<family lang="und-Medf">
- <font weight="400" style="normal">NotoSansMedefaidrin-VF.ttf
+ <font weight="400" style="normal">NotoSansMedefaidrin-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansMedefaidrin-VF.ttf
+ <font weight="500" style="normal">NotoSansMedefaidrin-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansMedefaidrin-VF.ttf
+ <font weight="600" style="normal">NotoSansMedefaidrin-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansMedefaidrin-VF.ttf
+ <font weight="700" style="normal">NotoSansMedefaidrin-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Soyo">
- <font weight="400" style="normal">NotoSansSoyombo-VF.ttf
+ <font weight="400" style="normal">NotoSansSoyombo-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansSoyombo-VF.ttf
+ <font weight="500" style="normal">NotoSansSoyombo-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansSoyombo-VF.ttf
+ <font weight="600" style="normal">NotoSansSoyombo-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansSoyombo-VF.ttf
+ <font weight="700" style="normal">NotoSansSoyombo-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Takr">
- <font weight="400" style="normal">NotoSansTakri-VF.ttf
+ <font weight="400" style="normal">NotoSansTakri-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSansTakri-VF.ttf
+ <font weight="500" style="normal">NotoSansTakri-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSansTakri-VF.ttf
+ <font weight="600" style="normal">NotoSansTakri-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSansTakri-VF.ttf
+ <font weight="700" style="normal">NotoSansTakri-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Hmnp">
- <font weight="400" style="normal">NotoSerifNyiakengPuachueHmong-VF.ttf
+ <font weight="400" style="normal">NotoSerifHmongNyiakeng-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSerifNyiakengPuachueHmong-VF.ttf
+ <font weight="500" style="normal">NotoSerifHmongNyiakeng-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSerifNyiakengPuachueHmong-VF.ttf
+ <font weight="600" style="normal">NotoSerifHmongNyiakeng-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSerifNyiakengPuachueHmong-VF.ttf
+ <font weight="700" style="normal">NotoSerifHmongNyiakeng-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
<family lang="und-Yezi">
- <font weight="400" style="normal">NotoSerifYezidi-VF.ttf
+ <font weight="400" style="normal">NotoSerifYezidi-Regular.ttf
<axis tag="wght" stylevalue="400"/>
</font>
- <font weight="500" style="normal">NotoSerifYezidi-VF.ttf
+ <font weight="500" style="normal">NotoSerifYezidi-Regular.ttf
<axis tag="wght" stylevalue="500"/>
</font>
- <font weight="600" style="normal">NotoSerifYezidi-VF.ttf
+ <font weight="600" style="normal">NotoSerifYezidi-Regular.ttf
<axis tag="wght" stylevalue="600"/>
</font>
- <font weight="700" style="normal">NotoSerifYezidi-VF.ttf
+ <font weight="700" style="normal">NotoSerifYezidi-Regular.ttf
<axis tag="wght" stylevalue="700"/>
</font>
</family>
diff --git a/data/keyboards/OWNERS b/data/keyboards/OWNERS
index c4f6df8..0ce8350 100644
--- a/data/keyboards/OWNERS
+++ b/data/keyboards/OWNERS
@@ -1,5 +1,3 @@
set noparent
-michaelwr@google.com
-svv@google.com
-lzye@google.com
+include /services/core/java/com/android/server/input/OWNERS
diff --git a/graphics/java/android/graphics/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
index d59abb5..189be53 100644
--- a/graphics/java/android/graphics/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -69,28 +69,26 @@
// animation & drawing system
public static final int VSYNC = 3;
- // The time of the oldest input event
- public static final int OLDEST_INPUT_EVENT = 4;
-
- // The time of the newest input event
- public static final int NEWEST_INPUT_EVENT = 5;
+ // The id of the input event that caused the current frame
+ public static final int INPUT_EVENT_ID = 4;
// When input event handling started
- public static final int HANDLE_INPUT_START = 6;
+ public static final int HANDLE_INPUT_START = 5;
// When animation evaluations started
- public static final int ANIMATION_START = 7;
+ public static final int ANIMATION_START = 6;
// When ViewRootImpl#performTraversals() started
- public static final int PERFORM_TRAVERSALS_START = 8;
+ public static final int PERFORM_TRAVERSALS_START = 7;
// When View:draw() started
- public static final int DRAW_START = 9;
+ public static final int DRAW_START = 8;
// When the frame needs to be ready by
- public static final int FRAME_DEADLINE = 10;
+ public static final int FRAME_DEADLINE = 9;
// Must be the last one
+ // This value must be in sync with `UI_THREAD_FRAME_INFO_SIZE` in FrameInfo.h
private static final int FRAME_INFO_SIZE = FRAME_DEADLINE + 1;
/** checkstyle */
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl
index f708298..684eebe 100644
--- a/keystore/java/android/security/IKeyChainService.aidl
+++ b/keystore/java/android/security/IKeyChainService.aidl
@@ -37,8 +37,6 @@
void setUserSelectable(String alias, boolean isUserSelectable);
int generateKeyPair(in String algorithm, in ParcelableKeyGenParameterSpec spec);
- int attestKey(in String alias, in byte[] challenge, in int[] idAttestationFlags,
- out KeymasterCertificateChain chain);
boolean setKeyPairCertificate(String alias, in byte[] userCert, in byte[] certChain);
// APIs used by CertInstaller and DevicePolicyManager
@@ -65,6 +63,7 @@
AppUriAuthenticationPolicy getCredentialManagementAppPolicy();
String getPredefinedAliasForPackageAndUri(String packageName, in Uri uri);
void removeCredentialManagementApp();
+ boolean isCredentialManagementApp(String packageName);
// APIs used by KeyChainActivity
void setGrant(int uid, String alias, boolean value);
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 97819c5..65a81cd 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -44,6 +44,8 @@
import android.security.keystore.AndroidKeyStoreProvider;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
+import android.system.keystore2.Domain;
+import android.system.keystore2.KeyDescriptor;
import android.util.Log;
import com.android.org.conscrypt.TrustedCertificateStore;
@@ -421,6 +423,15 @@
* credentials. This is limited to unmanaged devices. The authentication policy must be
* provided to be able to make this request successfully.
*
+ * <p> This intent should be started using {@link Activity#startActivityForResult(Intent, int)}
+ * to verify whether the request was successful and whether the user accepted or denied the
+ * request. If the user successfully receives and accepts the request, the result code will be
+ * {@link Activity#RESULT_OK}, otherwise the result code will be
+ * {@link Activity#RESULT_CANCELED}.
+ *
+ * <p> {@link KeyChain#isCredentialManagementApp(Context)} should be used to determine whether
+ * an app is already the credential management app.
+ *
* @param policy The authentication policy determines which alias for a private key and
* certificate pair should be used for authentication.
*/
@@ -589,6 +600,55 @@
}
/**
+ * Check whether the caller is the credential management app {@link CredentialManagementApp}.
+ * The credential management app has the ability to manage the user's KeyChain credentials
+ * on unmanaged devices.
+ *
+ * <p> {@link KeyChain#createManageCredentialsIntent} should be used by an app to request to
+ * become the credential management app. The user must approve this request before the app can
+ * manage the user's credentials. There can only be one credential management on the device.
+ *
+ * @return {@code true} if the caller is the credential management app.
+ */
+ public static boolean isCredentialManagementApp(@NonNull Context context) {
+ boolean isCredentialManagementApp = false;
+ try (KeyChainConnection keyChainConnection = KeyChain.bind(context)) {
+ isCredentialManagementApp = keyChainConnection.getService()
+ .isCredentialManagementApp(context.getPackageName());
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while checking whether the caller is the "
+ + "credential management app.", e);
+ } catch (SecurityException e) {
+ isCredentialManagementApp = false;
+ }
+ return isCredentialManagementApp;
+ }
+
+ /**
+ * Called by the credential management app to get the authentication policy
+ * {@link AppUriAuthenticationPolicy}.
+ *
+ * @return the credential management app's authentication policy.
+ * @throws SecurityException if the caller is not the credential management app.
+ */
+ @NonNull
+ public static AppUriAuthenticationPolicy getCredentialManagementAppPolicy(
+ @NonNull Context context) throws SecurityException {
+ AppUriAuthenticationPolicy policy = null;
+ try (KeyChainConnection keyChainConnection = KeyChain.bind(context)) {
+ policy = keyChainConnection.getService().getCredentialManagementAppPolicy();
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(
+ "Interrupted while getting credential management app policy.", e);
+ }
+ return policy;
+ }
+
+ /**
* Set a credential management app. The credential management app has the ability to manage
* the user's KeyChain credentials on unmanaged devices.
*
@@ -682,6 +742,33 @@
return null;
}
+ /**
+ * This prefix is used to disambiguate grant aliase strings from normal key alias strings.
+ * Technically, a key alias string can use the same prefix. However, a collision does not
+ * lead to privilege escalation, because grants are access controlled in the Keystore daemon.
+ * @hide
+ */
+ public static final String GRANT_ALIAS_PREFIX = "ks2_keychain_grant_id:";
+
+ private static KeyDescriptor getGrantDescriptor(String keyid) {
+ KeyDescriptor result = new KeyDescriptor();
+ result.domain = Domain.GRANT;
+ result.blob = null;
+ result.alias = null;
+ try {
+ result.nspace = Long.parseUnsignedLong(
+ keyid.substring(GRANT_ALIAS_PREFIX.length()), 16 /* radix */);
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ return result;
+ }
+
+ /** @hide */
+ public static String getGrantString(KeyDescriptor key) {
+ return String.format(GRANT_ALIAS_PREFIX + "%016X", key.nspace);
+ }
+
/** @hide */
@Nullable @WorkerThread
public static KeyPair getKeyPair(@NonNull Context context, @NonNull String alias)
@@ -705,11 +792,23 @@
if (keyId == null) {
return null;
+ }
+
+ if (AndroidKeyStoreProvider.isKeystore2Enabled()) {
+ try {
+ return android.security.keystore2.AndroidKeyStoreProvider
+ .loadAndroidKeyStoreKeyPairFromKeystore(
+ KeyStore2.getInstance(),
+ getGrantDescriptor(keyId));
+ } catch (UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
+ throw new KeyChainException(e);
+ }
} else {
try {
return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
KeyStore.getInstance(), keyId, KeyStore.UID_SELF);
- } catch (RuntimeException | UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
+ } catch (RuntimeException | UnrecoverableKeyException
+ | KeyPermanentlyInvalidatedException e) {
throw new KeyChainException(e);
}
}
@@ -827,11 +926,8 @@
@Deprecated
public static boolean isBoundKeyAlgorithm(
@NonNull @KeyProperties.KeyAlgorithmEnum String algorithm) {
- if (!isKeyAlgorithmSupported(algorithm)) {
- return false;
- }
-
- return KeyStore.getInstance().isHardwareBacked(algorithm);
+ // All supported algorithms are hardware backed. Individual keys may not be.
+ return true;
}
/** @hide */
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index e101115..35059ac 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -273,10 +273,10 @@
/** @hide **/
@NonNull
public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
- @NonNull KeyStore2 keyStore, @NonNull String privateKeyAlias, int namespace)
+ @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)
throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
AndroidKeyStoreKey key =
- loadAndroidKeyStoreKeyFromKeystore(keyStore, privateKeyAlias, namespace);
+ loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor);
if (key instanceof AndroidKeyStorePublicKey) {
AndroidKeyStorePublicKey publicKey = (AndroidKeyStorePublicKey) key;
return new KeyPair(publicKey, publicKey.getPrivateKey());
@@ -336,7 +336,7 @@
@NonNull
public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore(
@NonNull KeyStore2 keyStore, @NonNull String alias, int namespace)
- throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
+ throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
KeyDescriptor descriptor = new KeyDescriptor();
if (namespace == KeyProperties.NAMESPACE_APPLICATION) {
@@ -348,6 +348,18 @@
}
descriptor.alias = alias;
descriptor.blob = null;
+
+ final AndroidKeyStoreKey key = loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor);
+ if (key instanceof AndroidKeyStorePublicKey) {
+ return ((AndroidKeyStorePublicKey) key).getPrivateKey();
+ } else {
+ return key;
+ }
+ }
+
+ private static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore(
+ @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor)
+ throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
KeyEntryResponse response = null;
try {
response = keyStore.getKeyEntry(descriptor);
@@ -397,7 +409,7 @@
keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata,
new KeyStoreSecurityLevel(response.iSecurityLevel),
- keymasterAlgorithm).getPrivateKey();
+ keymasterAlgorithm);
} else {
throw new UnrecoverableKeyException("Key algorithm unknown");
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShellWrapper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShellWrapper.java
index 59271e9..e6e6d4a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShellWrapper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShellWrapper.java
@@ -22,7 +22,7 @@
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PinnedStackListenerForwarder;
-import com.android.wm.shell.pip.PinnedStackListenerForwarder.PinnedStackListener;
+import com.android.wm.shell.pip.PinnedStackListenerForwarder.PinnedTaskListener;
/**
* The singleton wrapper to communicate between WindowManagerService and WMShell features
@@ -46,7 +46,7 @@
* Adds a pinned stack listener, which will receive updates from the window manager service
* along with any other pinned stack listeners that were added via this method.
*/
- public void addPinnedStackListener(PinnedStackListener listener)
+ public void addPinnedStackListener(PinnedTaskListener listener)
throws RemoteException {
mPinnedStackListenerForwarder.addListener(listener);
mPinnedStackListenerForwarder.register(DEFAULT_DISPLAY);
@@ -55,7 +55,7 @@
/**
* Removes a pinned stack listener.
*/
- public void removePinnedStackListener(PinnedStackListener listener) {
+ public void removePinnedStackListener(PinnedTaskListener listener) {
mPinnedStackListenerForwarder.removeListener(listener);
}
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 79f9dcd..562b32b 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
@@ -34,6 +34,7 @@
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.DisplayImeController;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.split.SplitLayout;
@@ -57,12 +58,14 @@
private final AppPairsController mController;
private final SyncTransactionQueue mSyncQueue;
private final DisplayController mDisplayController;
+ private final DisplayImeController mDisplayImeController;
private SplitLayout mSplitLayout;
AppPair(AppPairsController controller) {
mController = controller;
mSyncQueue = controller.getSyncTransactionQueue();
mDisplayController = controller.getDisplayController();
+ mDisplayImeController = controller.getDisplayImeController();
}
int getRootTaskId() {
@@ -97,7 +100,7 @@
mSplitLayout = new SplitLayout(TAG + "SplitDivider",
mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
mRootTaskInfo.configuration, this /* layoutChangeListener */,
- b -> b.setParent(mRootTaskLeash));
+ b -> b.setParent(mRootTaskLeash), mDisplayImeController);
final WindowContainerToken token1 = task1.token;
final WindowContainerToken token2 = task2.token;
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 0415f12..b159333 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
@@ -23,17 +23,16 @@
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.DisplayImeController;
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}.
@@ -50,12 +49,15 @@
// Active app-pairs mapped by root task id key.
private final SparseArray<AppPair> mActiveAppPairs = new SparseArray<>();
private final DisplayController mDisplayController;
+ private final DisplayImeController mDisplayImeController;
public AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
- DisplayController displayController, ShellExecutor mainExecutor) {
+ DisplayController displayController, ShellExecutor mainExecutor,
+ DisplayImeController displayImeController) {
mTaskOrganizer = organizer;
mSyncQueue = syncQueue;
mDisplayController = displayController;
+ mDisplayImeController = displayImeController;
mMainExecutor = mainExecutor;
}
@@ -130,18 +132,22 @@
}
}
- public ShellTaskOrganizer getTaskOrganizer() {
+ ShellTaskOrganizer getTaskOrganizer() {
return mTaskOrganizer;
}
- public SyncTransactionQueue getSyncTransactionQueue() {
+ SyncTransactionQueue getSyncTransactionQueue() {
return mSyncQueue;
}
- public DisplayController getDisplayController() {
+ DisplayController getDisplayController() {
return mDisplayController;
}
+ DisplayImeController getDisplayImeController() {
+ return mDisplayImeController;
+ }
+
public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
final String childPrefix = innerPrefix + " ";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 047df5b..1320780 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1213,7 +1213,7 @@
/** PinnedStackListener that dispatches IME visibility updates to the stack. */
//TODO(b/170442945): Better way to do this / insets listener?
- private class BubblesImeListener extends PinnedStackListenerForwarder.PinnedStackListener {
+ private class BubblesImeListener extends PinnedStackListenerForwarder.PinnedTaskListener {
@Override
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
if (mStackView != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index a3edc20..a8ab406 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1539,19 +1539,16 @@
* Update bubble order and pointer position.
*/
public void updateBubbleOrder(List<Bubble> bubbles) {
- if (isExpansionAnimating()) {
- return;
- }
final Runnable reorder = () -> {
for (int i = 0; i < bubbles.size(); i++) {
Bubble bubble = bubbles.get(i);
mBubbleContainer.reorderView(bubble.getIconView(), i);
}
};
- if (mIsExpanded) {
+ if (mIsExpanded || isExpansionAnimating()) {
reorder.run();
updateBadgesAndZOrder(false /* setBadgeForCollapsedStack */);
- } else {
+ } else if (!isExpansionAnimating()) {
List<View> bubbleViews = bubbles.stream()
.map(b -> b.getIconView()).collect(Collectors.toList());
mStackAnimationController.animateReorder(bubbleViews, reorder);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index 58a4baf..f118b1e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -22,6 +22,8 @@
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.os.Process.SYSTEM_UID;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
+import static android.util.RotationUtils.rotateBounds;
+import static android.util.RotationUtils.rotateInsets;
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
@@ -37,7 +39,6 @@
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.DisplayMetrics;
-import android.util.RotationUtils;
import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
@@ -49,6 +50,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
/**
* Contains information about the layout-properties of a display. This refers to internal layout
@@ -81,6 +83,31 @@
private boolean mHasStatusBar = false;
private int mNavBarFrameHeight = 0;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DisplayLayout)) return false;
+ final DisplayLayout other = (DisplayLayout) o;
+ return mUiMode == other.mUiMode
+ && mWidth == other.mWidth
+ && mHeight == other.mHeight
+ && Objects.equals(mCutout, other.mCutout)
+ && mRotation == other.mRotation
+ && mDensityDpi == other.mDensityDpi
+ && Objects.equals(mNonDecorInsets, other.mNonDecorInsets)
+ && Objects.equals(mStableInsets, other.mStableInsets)
+ && mHasNavigationBar == other.mHasNavigationBar
+ && mHasStatusBar == other.mHasStatusBar
+ && mNavBarFrameHeight == other.mNavBarFrameHeight;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUiMode, mWidth, mHeight, mCutout, mRotation, mDensityDpi,
+ mNonDecorInsets, mStableInsets, mHasNavigationBar, mHasStatusBar,
+ mNavBarFrameHeight);
+ }
+
/**
* Create empty layout.
*/
@@ -241,38 +268,6 @@
}
/**
- * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta`
- * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and
- * remains at 0,0 after rotation.
- *
- * Only 'bounds' is mutated.
- */
- public static void rotateBounds(Rect inOutBounds, Rect parentBounds, int delta) {
- int rdelta = ((delta % 4) + 4) % 4;
- int origLeft = inOutBounds.left;
- switch (rdelta) {
- case 0:
- return;
- case 1:
- inOutBounds.left = inOutBounds.top;
- inOutBounds.top = parentBounds.right - inOutBounds.right;
- inOutBounds.right = inOutBounds.bottom;
- inOutBounds.bottom = parentBounds.right - origLeft;
- return;
- case 2:
- inOutBounds.left = parentBounds.right - inOutBounds.right;
- inOutBounds.right = parentBounds.right - origLeft;
- return;
- case 3:
- inOutBounds.left = parentBounds.bottom - inOutBounds.bottom;
- inOutBounds.bottom = inOutBounds.right;
- inOutBounds.right = parentBounds.bottom - inOutBounds.top;
- inOutBounds.top = origLeft;
- return;
- }
- }
-
- /**
* Calculates the stable insets if we already have the non-decor insets.
*/
private static void convertNonDecorInsetsToStableInsets(Resources res, Rect inOutInsets,
@@ -359,8 +354,7 @@
if (rotation == ROTATION_0) {
return computeSafeInsets(cutout, displayWidth, displayHeight);
}
- final Insets waterfallInsets =
- RotationUtils.rotateInsets(cutout.getWaterfallInsets(), rotation);
+ final Insets waterfallInsets = rotateInsets(cutout.getWaterfallInsets(), rotation);
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
Rect[] cutoutRects = cutout.getBoundingRectsAll();
final Rect[] newBounds = new Rect[cutoutRects.length];
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
index e94080a..3b67005 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
@@ -227,7 +227,7 @@
}
@Override
- public void onActivityDismissingDockedStack() {
+ public void onActivityDismissingDockedTask() {
mMainHandler.sendEmptyMessage(ON_ACTIVITY_DISMISSING_DOCKED_STACK);
}
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 c27c929..b9fdaa1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -36,11 +36,13 @@
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.R;
import com.android.wm.shell.animation.Interpolators;
+import com.android.wm.shell.common.DisplayImeController;
/**
- * Stack divider for app pair.
+ * Divider for multi window splits.
*/
-public class DividerView extends FrameLayout implements View.OnTouchListener {
+public class DividerView extends FrameLayout implements View.OnTouchListener,
+ DisplayImeController.ImePositionProcessor {
public static final long TOUCH_ANIMATION_DURATION = 150;
public static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
@@ -56,6 +58,7 @@
private boolean mMoving;
private int mStartPos;
private GestureDetector mDoubleTapDetector;
+ private boolean mInteractive;
public DividerView(@NonNull Context context) {
super(context);
@@ -91,12 +94,19 @@
mTouchElevation = getResources().getDimensionPixelSize(
R.dimen.docked_stack_divider_lift_elevation);
mDoubleTapDetector = new GestureDetector(getContext(), new DoubleTapListener());
+ mInteractive = true;
setOnTouchListener(this);
}
@Override
+ public void onImeVisibilityChanged(int displayId, boolean isShowing) {
+ if (displayId != getDisplay().getDisplayId()) return;
+ setInteractive(!isShowing);
+ }
+
+ @Override
public boolean onTouch(View v, MotionEvent event) {
- if (mSplitLayout == null) {
+ if (mSplitLayout == null || !mInteractive) {
return false;
}
@@ -202,6 +212,13 @@
mViewHost.relayout(lp);
}
+ private void setInteractive(boolean interactive) {
+ if (interactive == mInteractive) return;
+ mInteractive = interactive;
+ releaseTouching();
+ mHandle.setVisibility(mInteractive ? View.VISIBLE : View.INVISIBLE);
+ }
+
private boolean isLandscape() {
return getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE;
}
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 60231df..bacff78 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
@@ -35,6 +35,7 @@
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.animation.Interpolators;
+import com.android.wm.shell.common.DisplayImeController;
/**
* Records and handles layout of splits. Helps to calculate proper bounds when configuration or
@@ -59,11 +60,13 @@
public SplitLayout(String windowName, Context context, Configuration configuration,
LayoutChangeListener layoutChangeListener,
- SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks) {
+ SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
+ DisplayImeController displayImeController) {
mContext = context.createConfigurationContext(configuration);
mLayoutChangeListener = layoutChangeListener;
mSplitWindowManager = new SplitWindowManager(
- windowName, mContext, configuration, parentContainerCallbacks);
+ windowName, mContext, configuration, parentContainerCallbacks,
+ displayImeController);
mDividerWindowWidth = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
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 87f0c25..f6efb01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -46,6 +46,7 @@
import androidx.annotation.Nullable;
import com.android.wm.shell.R;
+import com.android.wm.shell.common.DisplayImeController;
/**
* Holds view hierarchy of a root surface and helps to inflate {@link DividerView} for a split.
@@ -53,23 +54,27 @@
public final class SplitWindowManager extends WindowlessWindowManager {
private static final String TAG = SplitWindowManager.class.getSimpleName();
+ private final String mWindowName;
+ private final DisplayImeController mDisplayImeController;
private final ParentContainerCallbacks mParentContainerCallbacks;
private Context mContext;
private SurfaceControlViewHost mViewHost;
private SurfaceControl mLeash;
private boolean mResizingSplits;
- private final String mWindowName;
+ private DividerView mDividerView;
public interface ParentContainerCallbacks {
void attachToParentSurface(SurfaceControl.Builder b);
}
public SplitWindowManager(String windowName, Context context, Configuration config,
- ParentContainerCallbacks parentContainerCallbacks) {
+ ParentContainerCallbacks parentContainerCallbacks,
+ DisplayImeController displayImeController) {
super(config, null /* rootSurface */, null /* hostInputToken */);
mContext = context.createConfigurationContext(config);
mParentContainerCallbacks = parentContainerCallbacks;
mWindowName = windowName;
+ mDisplayImeController = displayImeController;
}
@Override
@@ -103,14 +108,16 @@
/** Inflates {@link DividerView} on to the root surface. */
void init(SplitLayout splitLayout) {
- if (mViewHost == null) {
- mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+ if (mDividerView != null || mViewHost != null) {
+ throw new UnsupportedOperationException(
+ "Try to inflate divider view again without release first");
}
- final Rect dividerBounds = splitLayout.getDividerBounds();
- final DividerView dividerView = (DividerView) LayoutInflater.from(mContext)
+ mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+ mDividerView = (DividerView) LayoutInflater.from(mContext)
.inflate(R.layout.split_divider, null /* root */);
+ final Rect dividerBounds = splitLayout.getDividerBounds();
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
dividerBounds.width(), dividerBounds.height(), TYPE_DOCK_DIVIDER,
FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL | FLAG_WATCH_OUTSIDE_TOUCH
@@ -119,8 +126,9 @@
lp.token = new Binder();
lp.setTitle(mWindowName);
lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
- mViewHost.setView(dividerView, lp);
- dividerView.setup(splitLayout, mViewHost);
+ mViewHost.setView(mDividerView, lp);
+ mDividerView.setup(splitLayout, mViewHost);
+ mDisplayImeController.addPositionProcessor(mDividerView);
}
/**
@@ -128,6 +136,11 @@
* hierarchy.
*/
void release() {
+ if (mDividerView != null) {
+ mDisplayImeController.removePositionProcessor(mDividerView);
+ mDividerView = null;
+ }
+
if (mViewHost != null){
mViewHost.release();
mViewHost = null;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
index 477ec33..40244fb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
@@ -18,6 +18,7 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.util.RotationUtils.rotateBounds;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_LEFT;
@@ -244,7 +245,7 @@
DividerSnapAlgorithm snap = initSnapAlgorithmForRotation(context, tmpDL, dividerSize);
tmpRect.set(bounds);
- DisplayLayout.rotateBounds(tmpRect, displayRect, rotation - dl.rotation());
+ rotateBounds(tmpRect, displayRect, dl.rotation(), rotation);
rotatedDisplayRect.set(0, 0, tmpDL.width(), tmpDL.height());
final int dockSide = getPrimarySplitSide(tmpRect, rotatedDisplayRect,
tmpDL.getOrientation());
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 c8f8987..82468ad 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
@@ -105,7 +105,7 @@
synchronized (mDockedRect) {
mTouchableRegion.set(region);
}
- WindowManagerGlobal.getWindowManagerService().setDockedStackDividerTouchRegion(
+ WindowManagerGlobal.getWindowManagerService().setDockedTaskDividerTouchRegion(
mTouchableRegion);
} catch (RemoteException e) {
Log.w(TAG, "Failed to set touchable region: " + e);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index afc8a09..4c5cc22 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -202,6 +202,7 @@
animateWindows(token, leash, fromBounds, toBounds, direction,
mEnterExitAnimationDurationMs);
wct.setBounds(token, toBounds);
+ wct.setAppBounds(token, toBounds);
});
applyTransaction(wct);
}
@@ -231,6 +232,7 @@
// DisplayRotationController will applyTransaction() after finish rotating
if (wct != null) {
wct.setBounds(token, null/* reset */);
+ wct.setAppBounds(token, null/* reset */);
}
});
tx.apply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
index 8f8ec47..b3b1ba7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PinnedStackListenerForwarder.java
@@ -20,7 +20,7 @@
import android.content.ComponentName;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
-import android.view.IPinnedStackListener;
+import android.view.IPinnedTaskListener;
import android.view.WindowManagerGlobal;
import androidx.annotation.BinderThread;
@@ -32,66 +32,66 @@
/**
* PinnedStackListener that simply forwards all calls to each listener added via
* {@link #addListener}. This is necessary since calling
- * {@link com.android.server.wm.WindowManagerService#registerPinnedStackListener} replaces any
+ * {@link com.android.server.wm.WindowManagerService#registerPinnedTaskListener} replaces any
* previously set listener.
*/
public class PinnedStackListenerForwarder {
- private final IPinnedStackListener mListenerImpl = new PinnedStackListenerImpl();
+ private final IPinnedTaskListener mListenerImpl = new PinnedTaskListenerImpl();
private final ShellExecutor mMainExecutor;
- private final ArrayList<PinnedStackListener> mListeners = new ArrayList<>();
+ private final ArrayList<PinnedTaskListener> mListeners = new ArrayList<>();
public PinnedStackListenerForwarder(ShellExecutor mainExecutor) {
mMainExecutor = mainExecutor;
}
/** Adds a listener to receive updates from the WindowManagerService. */
- public void addListener(PinnedStackListener listener) {
+ public void addListener(PinnedTaskListener listener) {
mListeners.add(listener);
}
/** Removes a listener so it will no longer receive updates from the WindowManagerService. */
- public void removeListener(PinnedStackListener listener) {
+ public void removeListener(PinnedTaskListener listener) {
mListeners.remove(listener);
}
public void register(int displayId) throws RemoteException {
- WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
+ WindowManagerGlobal.getWindowManagerService().registerPinnedTaskListener(
displayId, mListenerImpl);
}
private void onMovementBoundsChanged(boolean fromImeAdjustment) {
- for (PinnedStackListener listener : mListeners) {
+ for (PinnedTaskListener listener : mListeners) {
listener.onMovementBoundsChanged(fromImeAdjustment);
}
}
private void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
- for (PinnedStackListener listener : mListeners) {
+ for (PinnedTaskListener listener : mListeners) {
listener.onImeVisibilityChanged(imeVisible, imeHeight);
}
}
private void onActionsChanged(ParceledListSlice<RemoteAction> actions) {
- for (PinnedStackListener listener : mListeners) {
+ for (PinnedTaskListener listener : mListeners) {
listener.onActionsChanged(actions);
}
}
private void onActivityHidden(ComponentName componentName) {
- for (PinnedStackListener listener : mListeners) {
+ for (PinnedTaskListener listener : mListeners) {
listener.onActivityHidden(componentName);
}
}
private void onAspectRatioChanged(float aspectRatio) {
- for (PinnedStackListener listener : mListeners) {
+ for (PinnedTaskListener listener : mListeners) {
listener.onAspectRatioChanged(aspectRatio);
}
}
@BinderThread
- private class PinnedStackListenerImpl extends IPinnedStackListener.Stub {
+ private class PinnedTaskListenerImpl extends IPinnedTaskListener.Stub {
@Override
public void onMovementBoundsChanged(boolean fromImeAdjustment) {
mMainExecutor.execute(() -> {
@@ -129,10 +129,10 @@
}
/**
- * A counterpart of {@link IPinnedStackListener} with empty implementations.
+ * A counterpart of {@link IPinnedTaskListener} with empty implementations.
* Subclasses can ignore those methods they do not intend to take action upon.
*/
- public static class PinnedStackListener {
+ public static class PinnedTaskListener {
public void onMovementBoundsChanged(boolean fromImeAdjustment) {}
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index 5ffa988..a52db24 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.pip;
+import static android.util.RotationUtils.rotateBounds;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
@@ -33,7 +34,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.wm.shell.animation.Interpolators;
-import com.android.wm.shell.common.DisplayLayout;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -90,15 +90,15 @@
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
- private PipTransitionAnimator mCurrentAnimator;
-
- private ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
+ private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
ThreadLocal.withInitial(() -> {
AnimationHandler handler = new AnimationHandler();
handler.setProvider(new SfVsyncFrameCallbackProvider());
return handler;
});
+ private PipTransitionAnimator mCurrentAnimator;
+
public PipAnimationController(PipSurfaceTransactionHelper helper) {
mSurfaceTransactionHelper = helper;
}
@@ -268,6 +268,7 @@
if (mPipAnimationCallback != null) {
mPipAnimationCallback.onPipAnimationEnd(mTaskInfo, tx, this);
}
+ mTransitionDirection = TRANSITION_DIRECTION_NONE;
}
@Override
@@ -275,6 +276,7 @@
if (mPipAnimationCallback != null) {
mPipAnimationCallback.onPipAnimationCancel(mTaskInfo, this);
}
+ mTransitionDirection = TRANSITION_DIRECTION_NONE;
}
@Override public void onAnimationRepeat(Animator animation) {}
@@ -448,7 +450,7 @@
// Rotate the end bounds according to the rotation delta because the display will
// be rotated to the same orientation.
rotatedEndRect = new Rect(endValue);
- DisplayLayout.rotateBounds(rotatedEndRect, endValue, rotationDelta);
+ rotateBounds(rotatedEndRect, endValue, rotationDelta);
} else {
rotatedEndRect = null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 4a2a032..9a584c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -65,6 +65,7 @@
import com.android.wm.shell.pip.PipUtils;
import java.io.PrintWriter;
+import java.util.Objects;
import java.util.function.Consumer;
/**
@@ -93,17 +94,20 @@
protected PhonePipMenuController mMenuController;
protected PipTaskOrganizer mPipTaskOrganizer;
- protected PinnedStackListenerForwarder.PinnedStackListener mPinnedStackListener =
- new PipControllerPinnedStackListener();
+ protected PinnedStackListenerForwarder.PinnedTaskListener mPinnedTaskListener =
+ new PipControllerPinnedTaskListener();
/**
* Handler for display rotation changes.
*/
private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
- if (!mPipTaskOrganizer.isInPip() || mPipTaskOrganizer.isDeferringEnterPipAnimation()) {
- // Skip if we aren't in PIP or haven't actually entered PIP yet. We still need to update
- // the display layout in the bounds handler in this case.
+ if (!mPipTaskOrganizer.isInPip()
+ || mPipBoundsState.getDisplayLayout().rotation() == toRotation
+ || mPipTaskOrganizer.isDeferringEnterPipAnimation()) {
+ // Skip if the same rotation has been set or we aren't in PIP or haven't actually
+ // entered PIP yet. We still need to update the display layout in the bounds handler
+ // in this case.
onDisplayRotationChangedNotInPip(mContext, toRotation);
// do not forget to update the movement bounds as well.
updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */,
@@ -178,8 +182,8 @@
/**
* Handler for messages from the PIP controller.
*/
- private class PipControllerPinnedStackListener extends
- PinnedStackListenerForwarder.PinnedStackListener {
+ private class PipControllerPinnedTaskListener extends
+ PinnedStackListenerForwarder.PinnedTaskListener {
@Override
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
mPipBoundsState.setImeVisibility(imeVisible, imeHeight);
@@ -310,7 +314,7 @@
mPipBoundsState.setDisplayLayout(new DisplayLayout(context, context.getDisplay()));
try {
- mWindowManagerShellWrapper.addPinnedStackListener(mPinnedStackListener);
+ mWindowManagerShellWrapper.addPinnedStackListener(mPinnedTaskListener);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to register pinned stack listener", e);
}
@@ -378,6 +382,9 @@
}
private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) {
+ if (Objects.equals(layout, mPipBoundsState.getDisplayLayout())) {
+ return;
+ }
Runnable updateDisplayLayout = () -> {
mPipBoundsState.setDisplayLayout(layout);
updateMovementBounds(null /* toBounds */,
@@ -476,8 +483,11 @@
int launcherRotation, int shelfHeight) {
setShelfHeightLocked(shelfHeight > 0 /* visible */, shelfHeight);
onDisplayRotationChangedNotInPip(mContext, launcherRotation);
- return mPipTaskOrganizer.startSwipePipToHome(componentName, activityInfo,
+ final Rect entryBounds = mPipTaskOrganizer.startSwipePipToHome(componentName, activityInfo,
pictureInPictureParams);
+ // sync mPipBoundsState with the newly calculated bounds.
+ mPipBoundsState.setNormalBounds(entryBounds);
+ return entryBounds;
}
private void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index 56f183f..7098019 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -377,7 +377,7 @@
private void registerWmShellPinnedStackListener(WindowManagerShellWrapper wmShell) {
try {
- wmShell.addPinnedStackListener(new PinnedStackListenerForwarder.PinnedStackListener() {
+ wmShell.addPinnedStackListener(new PinnedStackListenerForwarder.PinnedTaskListener() {
@Override
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
if (DEBUG) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index b0167af..11548ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -42,6 +42,7 @@
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
@@ -62,18 +63,20 @@
private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
private final ShellExecutor mMainExecutor;
private final SplitScreenImpl mImpl = new SplitScreenImpl();
+ private final DisplayImeController mDisplayImeController;
private StageCoordinator mStageCoordinator;
public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, Context context,
RootTaskDisplayAreaOrganizer rootTDAOrganizer,
- ShellExecutor mainExecutor) {
+ ShellExecutor mainExecutor, DisplayImeController displayImeController) {
mTaskOrganizer = shellTaskOrganizer;
mSyncQueue = syncQueue;
mContext = context;
mRootTDAOrganizer = rootTDAOrganizer;
mMainExecutor = mainExecutor;
+ mDisplayImeController = displayImeController;
}
public SplitScreen asSplitScreen() {
@@ -84,7 +87,7 @@
if (mStageCoordinator == null) {
// TODO: Multi-display
mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
- mRootTDAOrganizer, mTaskOrganizer);
+ mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index e44c820..22c9751 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -39,6 +39,7 @@
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.split.SplitLayout;
@@ -79,10 +80,12 @@
private DisplayAreaInfo mDisplayAreaInfo;
private final Context mContext;
private final List<SplitScreen.SplitScreenListener> mListeners = new ArrayList<>();
+ private final DisplayImeController mDisplayImeController;
private boolean mExitSplitScreenOnHide = true;
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
- RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer) {
+ RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
+ DisplayImeController displayImeController) {
mContext = context;
mDisplayId = displayId;
mSyncQueue = syncQueue;
@@ -90,13 +93,14 @@
mTaskOrganizer = taskOrganizer;
mMainStage = new MainStage(mTaskOrganizer, mDisplayId, mMainStageListener, mSyncQueue);
mSideStage = new SideStage(mTaskOrganizer, mDisplayId, mSideStageListener, mSyncQueue);
+ mDisplayImeController = displayImeController;
mRootTDAOrganizer.registerListener(displayId, this);
}
@VisibleForTesting
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
- MainStage mainStage, SideStage sideStage) {
+ MainStage mainStage, SideStage sideStage, DisplayImeController displayImeController) {
mContext = context;
mDisplayId = displayId;
mSyncQueue = syncQueue;
@@ -104,6 +108,7 @@
mTaskOrganizer = taskOrganizer;
mMainStage = mainStage;
mSideStage = sideStage;
+ mDisplayImeController = displayImeController;
mRootTDAOrganizer.registerListener(displayId, this);
}
@@ -420,7 +425,8 @@
if (mSplitLayout == null) {
mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
mDisplayAreaInfo.configuration, this,
- b -> mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b));
+ b -> mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b),
+ mDisplayImeController);
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
index a57ac35..9dd25fe 100644
--- a/libs/WindowManager/Shell/tests/flicker/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "WMShellFlickerTests",
srcs: ["src/**/*.java", "src/**/*.kt"],
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 10aea51..35bab7a 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
@@ -18,8 +18,6 @@
import android.graphics.Region
import android.view.Surface
-import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.traces.layers.getVisibleBounds
@@ -32,15 +30,15 @@
fun FlickerTestParameter.appPairsDividerIsInvisible() {
assertLayersEnd {
- this.notExists(APP_PAIR_SPLIT_DIVIDER)
+ this.notContains(APP_PAIR_SPLIT_DIVIDER)
}
}
fun FlickerTestParameter.appPairsDividerBecomesVisible() {
assertLayers {
- this.hidesLayer(DOCKED_STACK_DIVIDER)
+ this.isInvisible(DOCKED_STACK_DIVIDER)
.then()
- .showsLayer(DOCKED_STACK_DIVIDER)
+ .isVisible(DOCKED_STACK_DIVIDER)
}
}
@@ -52,30 +50,30 @@
fun FlickerTestParameter.dockedStackDividerBecomesVisible() {
assertLayers {
- this.hidesLayer(DOCKED_STACK_DIVIDER)
+ this.isInvisible(DOCKED_STACK_DIVIDER)
.then()
- .showsLayer(DOCKED_STACK_DIVIDER)
+ .isVisible(DOCKED_STACK_DIVIDER)
}
}
fun FlickerTestParameter.dockedStackDividerBecomesInvisible() {
assertLayers {
- this.showsLayer(DOCKED_STACK_DIVIDER)
+ this.isVisible(DOCKED_STACK_DIVIDER)
.then()
- .hidesLayer(DOCKED_STACK_DIVIDER)
+ .isInvisible(DOCKED_STACK_DIVIDER)
}
}
fun FlickerTestParameter.dockedStackDividerIsInvisible() {
assertLayersEnd {
- this.notExists(DOCKED_STACK_DIVIDER)
+ this.notContains(DOCKED_STACK_DIVIDER)
}
}
fun FlickerTestParameter.appPairsPrimaryBoundsIsVisible(rotation: Int, primaryLayerName: String) {
assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
- this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
+ this.coversExactly(getPrimaryRegion(dividerRegion, rotation), primaryLayerName)
}
}
@@ -85,7 +83,7 @@
) {
assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
- this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
+ this.coversExactly(getPrimaryRegion(dividerRegion, rotation), primaryLayerName)
}
}
@@ -95,7 +93,7 @@
) {
assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
- this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
+ this.coversExactly(getSecondaryRegion(dividerRegion, rotation), secondaryLayerName)
}
}
@@ -105,7 +103,7 @@
) {
assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(DOCKED_STACK_DIVIDER)
- this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
+ this.coversExactly(getSecondaryRegion(dividerRegion, rotation), secondaryLayerName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index d2cfb0f..03b93c7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -18,3 +18,5 @@
const val IME_WINDOW_NAME = "InputMethod"
const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
+const val APP_PAIR_SPLIT_DIVIDER = "AppPairSplitDivider"
+const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
index 5d51b2f..90e7137 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.apppairs
-import android.os.Bundle
import android.os.SystemClock
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
@@ -48,7 +47,7 @@
testSpec: FlickerTestParameter
) : AppPairsTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
super.transition(this, it)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
index 77890ba..dc51b4f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
@@ -16,17 +16,16 @@
package com.android.wm.shell.flicker.apppairs
-import android.os.Bundle
import android.os.SystemClock
import android.platform.test.annotations.Presubmit
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.traces.layers.getVisibleBounds
+import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER
import com.android.wm.shell.flicker.appPairsDividerIsVisible
import com.android.wm.shell.flicker.helpers.AppPairsHelper
import org.junit.FixMethodOrder
@@ -46,7 +45,7 @@
class AppPairsTestPairPrimaryAndSecondaryApps(
testSpec: FlickerTestParameter
) : AppPairsTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
super.transition(this, it)
transitions {
@@ -75,10 +74,10 @@
fun appsEndingBounds() {
testSpec.assertLayersEnd {
val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
- this.hasVisibleRegion(primaryApp.defaultWindowName,
- appPairsHelper.getPrimaryBounds(dividerRegion))
- .hasVisibleRegion(secondaryApp.defaultWindowName,
- appPairsHelper.getSecondaryBounds(dividerRegion))
+ this.coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion),
+ primaryApp.defaultWindowName)
+ .coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion),
+ secondaryApp.defaultWindowName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
index 3d3ca0c..5bb9b2f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
@@ -16,17 +16,16 @@
package com.android.wm.shell.flicker.apppairs
-import android.os.Bundle
import android.os.SystemClock
import android.platform.test.annotations.Presubmit
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.APP_PAIR_SPLIT_DIVIDER
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.traces.layers.getVisibleBounds
+import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER
import com.android.wm.shell.flicker.appPairsDividerIsInvisible
import com.android.wm.shell.flicker.helpers.AppPairsHelper
import org.junit.FixMethodOrder
@@ -46,7 +45,7 @@
class AppPairsTestUnpairPrimaryAndSecondaryApps(
testSpec: FlickerTestParameter
) : AppPairsTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
super.transition(this, it)
setup {
@@ -80,10 +79,10 @@
fun appsStartingBounds() {
testSpec.assertLayersStart {
val dividerRegion = entry.getVisibleBounds(APP_PAIR_SPLIT_DIVIDER)
- hasVisibleRegion(primaryApp.defaultWindowName,
- appPairsHelper.getPrimaryBounds(dividerRegion))
- hasVisibleRegion(secondaryApp.defaultWindowName,
- appPairsHelper.getSecondaryBounds(dividerRegion))
+ coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion),
+ primaryApp.defaultWindowName)
+ coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion),
+ secondaryApp.defaultWindowName)
}
}
@@ -91,8 +90,8 @@
@Test
fun appsEndingBounds() {
testSpec.assertLayersEnd {
- notExists(primaryApp.defaultWindowName)
- notExists(secondaryApp.defaultWindowName)
+ notContains(primaryApp.defaultWindowName)
+ notContains(secondaryApp.defaultWindowName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTransition.kt
index 9e6752d..91e080f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTransition.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.apppairs
import android.app.Instrumentation
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.system.helpers.ActivityHelper
import android.util.Log
@@ -66,7 +65,7 @@
}
}
- internal open val transition: FlickerBuilder.(Bundle) -> Unit
+ internal open val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
setup {
test {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
index 35a0020..eb53783 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.apppairs
-import android.os.Bundle
import android.os.SystemClock
import android.platform.test.annotations.Presubmit
import android.view.Surface
@@ -52,7 +51,7 @@
class RotateTwoLaunchedAppsInAppPairsMode(
testSpec: FlickerTestParameter
) : RotateTwoLaunchedAppsTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
super.transition(this, it)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
index 326a775..39c9484 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.apppairs
-import android.os.Bundle
import android.os.SystemClock
import android.platform.test.annotations.Presubmit
import android.view.Surface
@@ -55,7 +54,7 @@
class RotateTwoLaunchedAppsRotateAndEnterAppPairsMode(
testSpec: FlickerTestParameter
) : RotateTwoLaunchedAppsTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
super.transition(this, it)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsTransition.kt
index 271b25f..83853e6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsTransition.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.apppairs
-import android.os.Bundle
import android.view.Surface
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.dsl.FlickerBuilder
@@ -30,7 +29,7 @@
override val nonResizeableApp: SplitScreenHelper?
get() = null
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
setup {
test {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
index 9b70fac..17c51fb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -50,11 +49,10 @@
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-// @FlakyTest(bugId = 179116910)
class EnterSplitScreenDockActivity(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
index bd57a59..a94fd46 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -54,7 +53,7 @@
class EnterSplitScreenLaunchToSide(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
index 67578b2..238059b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.view.Surface
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
@@ -50,7 +49,7 @@
class EnterSplitScreenNonResizableNotDock(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
teardown {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
index 5d42a4a..acd570a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
@@ -16,12 +16,10 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
@@ -34,6 +32,7 @@
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import org.junit.FixMethodOrder
import org.junit.Test
@@ -52,7 +51,7 @@
class ExitLegacySplitScreenFromBottom(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
setup {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
index ff8f9c6..cef1886 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -53,7 +52,7 @@
class ExitPrimarySplitScreenShowSecondaryFullscreen(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
teardown {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenRotateTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenRotateTransition.kt
index 893b101..1e89a25 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenRotateTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenRotateTransition.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.view.Surface
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.dsl.FlickerBuilder
@@ -27,7 +26,7 @@
abstract class LegacySplitScreenRotateTransition(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
setup {
eachRun {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
index 09a7e31..7f69a66 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.support.test.launcherhelper.LauncherStrategyFactory
import android.view.Surface
@@ -66,7 +65,7 @@
.launcherStrategy.supportedLauncherPackage
private val testApp = SimpleAppHelper(instrumentation)
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
setup {
test {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
index 6ab1f0b..91ea871 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
import android.app.Instrumentation
-import android.os.Bundle
import android.support.test.launcherhelper.LauncherStrategyFactory
import android.view.Surface
import androidx.test.platform.app.InstrumentationRegistry
@@ -41,7 +40,7 @@
protected val LAUNCHER_PACKAGE_NAME = LauncherStrategyFactory.getInstance(instrumentation)
.launcherStrategy.supportedLauncherPackage
- protected open val transition: FlickerBuilder.(Bundle) -> Unit
+ protected open val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
setup {
eachRun {
@@ -70,7 +69,7 @@
}
}
- internal open val cleanSetup: FlickerBuilder.(Bundle) -> Unit
+ internal open val cleanSetup: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
setup {
eachRun {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
index 1b4b54a..caafa27 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
@@ -16,12 +16,10 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
@@ -34,6 +32,7 @@
import com.android.server.wm.flicker.layerBecomesVisible
import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import org.junit.FixMethodOrder
import org.junit.Test
@@ -53,7 +52,7 @@
class NonResizableDismissInLegacySplitScreen(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
cleanSetup(this, configuration)
setup {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
index 2365e3b..543484a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
@@ -16,12 +16,10 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
@@ -33,6 +31,7 @@
import com.android.server.wm.flicker.layerBecomesVisible
import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import org.junit.FixMethodOrder
import org.junit.Test
@@ -53,7 +52,7 @@
class NonResizableLaunchInLegacySplitScreen(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
cleanSetup(this, configuration)
setup {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
index b369a3d..d228337 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -53,7 +52,7 @@
class OpenAppToLegacySplitScreen(
testSpec: FlickerTestParameter
) : LegacySplitScreenTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
index ffffa19..f5174bc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
@@ -17,13 +17,11 @@
package com.android.wm.shell.flicker.legacysplitscreen
import android.graphics.Region
-import android.os.Bundle
import android.util.Rational
import android.view.Surface
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.By
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
@@ -46,6 +44,7 @@
import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.traces.layers.getVisibleBounds
+import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER
import com.android.wm.shell.flicker.helpers.SimpleAppHelper
import org.junit.FixMethodOrder
import org.junit.Test
@@ -70,7 +69,7 @@
private val testAppTop = SimpleAppHelper(instrumentation)
private val testAppBottom = ImeAppHelper(instrumentation)
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
setup {
eachRun {
@@ -151,21 +150,21 @@
@Test
fun topAppLayerIsAlwaysVisible() {
testSpec.assertLayers {
- this.showsLayer(sSimpleActivity)
+ this.isVisible(sSimpleActivity)
}
}
@Test
fun bottomAppLayerIsAlwaysVisible() {
testSpec.assertLayers {
- this.showsLayer(sImeActivity)
+ this.isVisible(sImeActivity)
}
}
@Test
fun dividerLayerIsAlwaysVisible() {
testSpec.assertLayers {
- this.showsLayer(DOCKED_STACK_DIVIDER)
+ this.isVisible(DOCKED_STACK_DIVIDER)
}
}
@@ -183,8 +182,8 @@
dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
displayBounds.right,
displayBounds.bottom - WindowUtils.navigationBarHeight)
- this.hasVisibleRegion("SimpleActivity", topAppBounds)
- .hasVisibleRegion("ImeActivity", bottomAppBounds)
+ this.coversExactly(topAppBounds, "SimpleActivity")
+ .coversExactly(bottomAppBounds, "ImeActivity")
}
}
@@ -203,8 +202,8 @@
displayBounds.right,
displayBounds.bottom - WindowUtils.navigationBarHeight)
- this.hasVisibleRegion(sSimpleActivity, topAppBounds)
- .hasVisibleRegion(sImeActivity, bottomAppBounds)
+ this.coversExactly(topAppBounds, sSimpleActivity)
+ .coversExactly(bottomAppBounds, sImeActivity)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
index c538008..c914ada 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -54,7 +53,7 @@
class RotateOneLaunchedAppAndEnterSplitScreen(
testSpec: FlickerTestParameter
) : LegacySplitScreenRotateTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
index c116256..ffb20a4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -54,7 +53,7 @@
class RotateOneLaunchedAppInSplitScreenMode(
testSpec: FlickerTestParameter
) : LegacySplitScreenRotateTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
index 273925c..8cf1990 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -56,7 +55,7 @@
class RotateTwoLaunchedAppAndEnterSplitScreen(
testSpec: FlickerTestParameter
) : LegacySplitScreenRotateTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
transitions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
index c7188dc..9c798d8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.legacysplitscreen
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -56,7 +55,7 @@
class RotateTwoLaunchedAppInSplitScreenMode(
testSpec: FlickerTestParameter
) : LegacySplitScreenRotateTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
super.transition(this, configuration)
setup {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
index ca48eaa..75c33c6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -51,7 +50,7 @@
private val testApp = FixedAppHelper(instrumentation)
private val displayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = true) {
setup {
eachRun {
@@ -68,7 +67,7 @@
@Test
fun pipAppRemainInsideVisibleBounds() {
testSpec.assertWm {
- coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
+ coversAtMost(displayBounds, pipApp.defaultWindowName)
}
}
@@ -95,10 +94,10 @@
@Test
fun showBothAppLayersThenHidePip() {
testSpec.assertLayers {
- showsLayer(testApp.defaultWindowName)
- .showsLayer(pipApp.defaultWindowName)
+ isVisible(testApp.defaultWindowName)
+ .isVisible(pipApp.defaultWindowName)
.then()
- .hidesLayer(testApp.defaultWindowName)
+ .isInvisible(testApp.defaultWindowName)
}
}
@@ -106,8 +105,8 @@
@Test
fun testAppCoversFullScreenWithPipOnDisplay() {
testSpec.assertLayersStart {
- hasVisibleRegion(testApp.defaultWindowName, displayBounds)
- coversAtMostRegion(displayBounds, pipApp.defaultWindowName)
+ coversExactly(displayBounds, testApp.defaultWindowName)
+ coversAtMost(displayBounds, pipApp.defaultWindowName)
}
}
@@ -115,7 +114,7 @@
@Test
fun pipAppCoversFullScreen() {
testSpec.assertLayersEnd {
- hasVisibleRegion(pipApp.defaultWindowName, displayBounds)
+ coversExactly(displayBounds, pipApp.defaultWindowName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index e1fbc16..83dca53 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -48,7 +47,7 @@
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = true, stringExtras = emptyMap()) {
transitions {
pipApp.clickEnterPipButton()
@@ -85,7 +84,7 @@
@Test
fun pipLayerBecomesVisible() {
testSpec.assertLayers {
- this.showsLayer(pipApp.launcherName)
+ this.isVisible(pipApp.launcherName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index 215b97b..41e2864 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -56,7 +55,7 @@
private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
setupAndTeardown(this, configuration)
@@ -121,7 +120,7 @@
@Test
fun pipAppLayerHidesTestApp() {
testSpec.assertLayersStart {
- hasVisibleRegion(pipApp.defaultWindowName, startingBounds)
+ coversExactly(startingBounds, pipApp.defaultWindowName)
isInvisible(testApp.defaultWindowName)
}
}
@@ -130,7 +129,7 @@
@Test
fun testAppLayerCoversFullScreen() {
testSpec.assertLayersEnd {
- hasVisibleRegion(testApp.defaultWindowName, endingBounds)
+ coversExactly(endingBounds, testApp.defaultWindowName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
index 707d28d..96eb66c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/Extensions.kt
@@ -48,7 +48,7 @@
activity: ComponentName
): WindowManagerStateSubject = apply {
val windowName = activity.toWindowName()
- hasWindow(windowName)
+ contains(windowName)
val pinnedWindows = wmState.pinnedWindows
.map { it.title }
Truth.assertWithMessage("Window not in PIP mode")
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index f3b9ea1..4633960 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -46,7 +45,7 @@
class PipKeyboardTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
private val imeApp = ImeAppHelper(instrumentation)
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = false) { configuration ->
setup {
test {
@@ -78,7 +77,7 @@
fun pipInVisibleBounds() {
testSpec.assertWm {
val displayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
- coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
+ coversAtMost(displayBounds, pipApp.defaultWindowName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index daf381e..97afc65 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Postsubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -58,7 +57,7 @@
private val testApp = FixedAppHelper(instrumentation)
private val displayBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
withTestName { testSpec.name }
repeat { testSpec.config.repetitions }
@@ -90,7 +89,7 @@
@Test
fun pipWindowInsideDisplayBounds() {
testSpec.assertWm {
- coversAtMostRegion(pipApp.defaultWindowName, displayBounds)
+ coversAtMost(displayBounds, pipApp.defaultWindowName)
}
}
@@ -100,7 +99,7 @@
testSpec.assertWmEnd {
isVisible(testApp.defaultWindowName)
isVisible(imeApp.defaultWindowName)
- noWindowsOverlap(setOf(testApp.defaultWindowName, imeApp.defaultWindowName))
+ noWindowsOverlap(testApp.defaultWindowName, imeApp.defaultWindowName)
}
}
@@ -116,7 +115,7 @@
@Test
fun pipLayerInsideDisplayBounds() {
testSpec.assertLayers {
- coversAtMostRegion(displayBounds, pipApp.defaultWindowName)
+ coversAtMost(displayBounds, pipApp.defaultWindowName)
}
}
@@ -124,8 +123,8 @@
@Test
fun bothAppLayersVisible() {
testSpec.assertLayersEnd {
- coversAtMostRegion(displayBounds, testApp.defaultWindowName)
- coversAtMostRegion(displayBounds, imeApp.defaultWindowName)
+ coversAtMost(displayBounds, testApp.defaultWindowName)
+ coversAtMost(displayBounds, imeApp.defaultWindowName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index 43c12ac..37b49c7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -56,7 +55,7 @@
private val startingBounds = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
private val endingBounds = WindowUtils.getDisplayBounds(testSpec.config.endRotation)
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = false) { configuration ->
setup {
test {
@@ -113,8 +112,8 @@
@Test
fun appLayerRotates_StartingBounds() {
testSpec.assertLayersStart {
- hasVisibleRegion(fixedApp.defaultWindowName, startingBounds)
- coversAtMostRegion(startingBounds, pipApp.defaultWindowName)
+ coversExactly(startingBounds, fixedApp.defaultWindowName)
+ coversAtMost(startingBounds, pipApp.defaultWindowName)
}
}
@@ -122,8 +121,8 @@
@Test
fun appLayerRotates_EndingBounds() {
testSpec.assertLayersEnd {
- hasVisibleRegion(fixedApp.defaultWindowName, endingBounds)
- coversAtMostRegion(endingBounds, pipApp.defaultWindowName)
+ coversExactly(endingBounds, fixedApp.defaultWindowName)
+ coversAtMost(endingBounds, pipApp.defaultWindowName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
index 02389a9..704fd1d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -50,7 +49,7 @@
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class PipToAppTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = true) { configuration ->
setup {
eachRun {
@@ -102,9 +101,9 @@
@Test
fun appReplacesPipLayer() {
testSpec.assertLayers {
- this.showsLayer(PIP_WINDOW_TITLE)
+ this.isVisible(PIP_WINDOW_TITLE)
.then()
- .showsLayer(pipApp.launcherName)
+ .isVisible(pipApp.launcherName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
index 968a11d..06ef79a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
@@ -29,6 +28,7 @@
import com.android.server.wm.flicker.focusChanges
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.noUncoveredRegions
import com.android.server.wm.flicker.startRotation
@@ -50,7 +50,7 @@
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class PipToHomeTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = true) { configuration ->
setup {
eachRun {
@@ -97,9 +97,9 @@
@Test
fun pipLayerBecomesInvisible() {
testSpec.assertLayers {
- this.showsLayer(PIP_WINDOW_TITLE)
+ this.isVisible(PIP_WINDOW_TITLE)
.then()
- .hidesLayer(PIP_WINDOW_TITLE)
+ .isInvisible(PIP_WINDOW_TITLE)
}
}
@@ -116,7 +116,7 @@
@Postsubmit
@Test
fun navBarLayerRotatesAndScales() =
- testSpec.noUncoveredRegions(testSpec.config.startRotation, Surface.ROTATION_0)
+ testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
@FlakyTest(bugId = 151179149)
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index a94483e..b0a9afe 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -18,7 +18,6 @@
import android.app.Instrumentation
import android.content.Intent
-import android.os.Bundle
import android.view.Surface
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -38,7 +37,7 @@
protected val isRotated = testSpec.config.startRotation.isRotated()
protected val pipApp = PipAppHelper(instrumentation)
protected val broadcastActionTrigger = BroadcastActionTrigger(instrumentation)
- protected abstract val transition: FlickerBuilder.(Bundle) -> Unit
+ protected abstract val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
// Helper class to process test actions by broadcast.
protected class BroadcastActionTrigger(private val instrumentation: Instrumentation) {
@@ -81,7 +80,7 @@
/**
* Gets a configuration that handles basic setup and teardown of pip tests
*/
- protected val setupAndTeardown: FlickerBuilder.(Bundle) -> Unit
+ protected val setupAndTeardown: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = {
setup {
test {
@@ -112,8 +111,8 @@
protected open fun buildTransition(
eachRun: Boolean,
stringExtras: Map<String, String> = mapOf(Components.PipActivity.EXTRA_ENTER_PIP to "true"),
- extraSpec: FlickerBuilder.(Bundle) -> Unit = {}
- ): FlickerBuilder.(Bundle) -> Unit {
+ extraSpec: FlickerBuilder.(Map<String, Any?>) -> Unit = {}
+ ): FlickerBuilder.(Map<String, Any?>) -> Unit {
return { configuration ->
setupAndTeardown(this, configuration)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index 1f0370d..1fcc7d0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
@@ -54,7 +53,7 @@
private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
- override val transition: FlickerBuilder.(Bundle) -> Unit
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = { configuration ->
setupAndTeardown(this, configuration)
@@ -88,7 +87,7 @@
@Test
fun pipWindowInsideDisplay() {
testSpec.assertWmStart {
- coversAtMostRegion(pipApp.defaultWindowName, startingBounds)
+ coversAtMost(startingBounds, pipApp.defaultWindowName)
}
}
@@ -112,7 +111,7 @@
@Test
fun pipLayerInsideDisplay() {
testSpec.assertLayersStart {
- coversAtMostRegion(startingBounds, pipApp.defaultWindowName)
+ coversAtMost(startingBounds, pipApp.defaultWindowName)
}
}
@@ -120,7 +119,7 @@
@Test
fun pipAppLayerCoversFullScreen() {
testSpec.assertLayersEnd {
- hasVisibleRegion(pipApp.defaultWindowName, endingBounds)
+ coversExactly(endingBounds, pipApp.defaultWindowName)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
index 26627a4..ea606df 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "WMShellFlickerTestApp",
srcs: ["**/*.java"],
@@ -23,4 +32,4 @@
name: "wmshell-flicker-test-components",
srcs: ["src/**/Components.java"],
sdk_version: "test_current",
-}
\ No newline at end of file
+}
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 e094158..27c6261 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
@@ -20,17 +20,17 @@
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
-import org.mockito.Mock;
-
public class TestAppPairsController extends AppPairsController {
private TestAppPairsPool mPool;
public TestAppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
DisplayController displayController) {
- super(organizer, syncQueue, displayController, mock(ShellExecutor.class));
+ super(organizer, syncQueue, displayController, mock(ShellExecutor.class),
+ mock(DisplayImeController.class));
mPool = new TestAppPairsPool(this);
setPairsPool(mPool);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
index 2b5b77e..88e754c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
@@ -38,6 +38,12 @@
import org.junit.Test;
+/**
+ * Tests for {@link DisplayLayout}.
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:DisplayLayoutTest
+ */
@SmallTest
public class DisplayLayoutTest {
@@ -70,18 +76,6 @@
@Test
public void testRotate() {
// Basic rotate utility
- Rect testParent = new Rect(0, 0, 1000, 600);
- Rect testInner = new Rect(40, 20, 120, 80);
- Rect testResult = new Rect(testInner);
- DisplayLayout.rotateBounds(testResult, testParent, 1);
- assertEquals(new Rect(20, 880, 80, 960), testResult);
- testResult.set(testInner);
- DisplayLayout.rotateBounds(testResult, testParent, 2);
- assertEquals(new Rect(880, 20, 960, 80), testResult);
- testResult.set(testInner);
- DisplayLayout.rotateBounds(testResult, testParent, 3);
- assertEquals(new Rect(520, 40, 580, 120), testResult);
-
Resources res = createResources(40, 50, false, 30, 40);
DisplayInfo info = createDisplayInfo(1000, 1500, 60, ROTATION_0);
DisplayLayout dl = new DisplayLayout(info, res, true, true);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
index 21bc32c..d8aebc2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
@@ -198,7 +198,7 @@
@Test
public void testOnActivityDismissingDockedStack() {
- mImpl.onActivityDismissingDockedStack();
+ mImpl.onActivityDismissingDockedTask();
verify(mCallback).onActivityDismissingDockedStack();
verify(mOtherCallback).onActivityDismissingDockedStack();
}
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 5821eed..7b0e6b9 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
@@ -36,6 +36,7 @@
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayImeController;
import org.junit.Before;
import org.junit.Test;
@@ -49,6 +50,7 @@
public class SplitLayoutTests extends ShellTestCase {
@Mock SplitLayout.LayoutChangeListener mLayoutChangeListener;
@Mock SurfaceControl mRootLeash;
+ @Mock DisplayImeController mDisplayImeController;
private SplitLayout mSplitLayout;
@Before
@@ -59,7 +61,8 @@
mContext,
getConfiguration(false),
mLayoutChangeListener,
- b -> b.setParent(mRootLeash));
+ b -> b.setParent(mRootLeash),
+ mDisplayImeController);
}
@Test
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 698315a..86d0d82 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -29,6 +29,7 @@
import androidx.test.filters.SmallTest;
import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayImeController;
import org.junit.Before;
import org.junit.Test;
@@ -42,6 +43,7 @@
public class SplitWindowManagerTests extends ShellTestCase {
@Mock SurfaceControl mSurfaceControl;
@Mock SplitLayout mSplitLayout;
+ @Mock DisplayImeController mDisplayImeController;
private SplitWindowManager mSplitWindowManager;
@Before
@@ -50,7 +52,7 @@
final Configuration configuration = new Configuration();
configuration.setToDefaults();
mSplitWindowManager = new SplitWindowManager("TestSplitDivider", mContext, configuration,
- b -> b.setParent(mSurfaceControl));
+ b -> b.setParent(mSurfaceControl), mDisplayImeController);
when(mSplitLayout.getDividerBounds()).thenReturn(
new Rect(0, 0, configuration.windowConfiguration.getBounds().width(),
configuration.windowConfiguration.getBounds().height()));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
index 3147dab..63b9413 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.pip;
+import static android.util.RotationUtils.rotateBounds;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_90;
@@ -37,7 +38,6 @@
import androidx.test.filters.SmallTest;
import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.common.DisplayLayout;
import org.junit.Before;
import org.junit.Test;
@@ -141,7 +141,7 @@
// Apply fraction 1 to compute the end value.
animator.applySurfaceControlTransaction(mLeash, new DummySurfaceControlTx(), 1);
final Rect rotatedEndBounds = new Rect(endBounds);
- DisplayLayout.rotateBounds(rotatedEndBounds, endBounds, ROTATION_90);
+ rotateBounds(rotatedEndBounds, endBounds, ROTATION_90);
assertEquals("Expect 90 degree rotated bounds", rotatedEndBounds, animator.mCurrentValue);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index cfe8463..f2b4e97 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -124,7 +124,7 @@
final ComponentName component1 = new ComponentName(mContext, "component1");
when(mMockPipBoundsState.getLastPipComponentName()).thenReturn(component1);
- mPipController.mPinnedStackListener.onActivityHidden(component1);
+ mPipController.mPinnedTaskListener.onActivityHidden(component1);
verify(mMockPipBoundsState).setLastPipComponentName(null);
}
@@ -135,7 +135,7 @@
final ComponentName component2 = new ComponentName(mContext, "component2");
when(mMockPipBoundsState.getLastPipComponentName()).thenReturn(component1);
- mPipController.mPinnedStackListener.onActivityHidden(component2);
+ mPipController.mPinnedTaskListener.onActivityHidden(component2);
verify(mMockPipBoundsState, never()).setLastPipComponentName(null);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index d2d1812..74753aa 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -41,6 +41,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.DisplayImeController;
import com.android.wm.shell.common.SyncTransactionQueue;
import org.junit.Before;
@@ -58,13 +59,14 @@
@Mock private RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
@Mock private MainStage mMainStage;
@Mock private SideStage mSideStage;
+ @Mock private DisplayImeController mDisplayImeController;
private StageCoordinator mStageCoordinator;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mStageCoordinator = new TestStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
- mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage);
+ mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage, mDisplayImeController);
}
@Test
@@ -94,9 +96,9 @@
TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
- MainStage mainStage, SideStage sideStage) {
+ MainStage mainStage, SideStage sideStage, DisplayImeController imeController) {
super(context, displayId, syncQueue, rootTDAOrganizer, taskOrganizer, mainStage,
- sideStage);
+ sideStage, imeController);
// Prepare default TaskDisplayArea for testing.
mDisplayAreaInfo = new DisplayAreaInfo(
diff --git a/libs/androidfw/TEST_MAPPING b/libs/androidfw/TEST_MAPPING
index 777aa0b..766714c 100644
--- a/libs/androidfw/TEST_MAPPING
+++ b/libs/androidfw/TEST_MAPPING
@@ -1,10 +1,6 @@
{
"presubmit": [
{
- "name": "libandroidfw_tests",
- "host": true
- },
- {
"name": "CtsResourcesLoaderTests"
}
]
diff --git a/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
index b36ff09..3035a79 100644
--- a/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
+++ b/libs/androidfw/fuzz/cursorwindow_fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_libs_androidfw_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_libs_androidfw_license"],
+}
+
cc_fuzz {
name: "cursorwindow_fuzzer",
srcs: [
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 5d3f6f2..2448cc9 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -20,13 +20,12 @@
namespace android {
namespace uirenderer {
-const std::array<std::string, static_cast<int>(FrameInfoIndex::NumIndexes)> FrameInfoNames = {
+const std::array FrameInfoNames{
"Flags",
"FrameTimelineVsyncId",
"IntendedVsync",
"Vsync",
- "OldestInputEvent",
- "NewestInputEvent",
+ "InputEventId",
"HandleInputStart",
"AnimationStart",
"PerformTraversalsStart",
@@ -40,7 +39,8 @@
"DequeueBufferDuration",
"QueueBufferDuration",
"GpuCompleted",
- "SwapBuffersCompleted"
+ "SwapBuffersCompleted",
+ "DisplayPresentTime",
};
static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 20,
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index 45a367f..912d04c5 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -28,15 +28,14 @@
namespace android {
namespace uirenderer {
-#define UI_THREAD_FRAME_INFO_SIZE 11
+static constexpr size_t UI_THREAD_FRAME_INFO_SIZE = 10;
enum class FrameInfoIndex {
Flags = 0,
FrameTimelineVsyncId,
IntendedVsync,
Vsync,
- OldestInputEvent,
- NewestInputEvent,
+ InputEventId,
HandleInputStart,
AnimationStart,
PerformTraversalsStart,
@@ -56,13 +55,14 @@
GpuCompleted,
SwapBuffersCompleted,
+ DisplayPresentTime,
// Must be the last value!
// Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
NumIndexes
};
-extern const std::array<std::string, static_cast<int>(FrameInfoIndex::NumIndexes)> FrameInfoNames;
+extern const std::array<const char*, static_cast<int>(FrameInfoIndex::NumIndexes)> FrameInfoNames;
namespace FrameInfoFlags {
enum {
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 2cd9b7b..4eefe92 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -112,7 +112,7 @@
std::lock_guard lock(mDataMutex);
// Fast-path for jank-free frames
- int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted);
+ int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::SwapBuffersCompleted);
if (mDequeueTimeForgiveness && frame[FrameInfoIndex::DequeueBufferDuration] > 500_us) {
nsecs_t expectedDequeueDuration = mDequeueTimeForgiveness + frame[FrameInfoIndex::Vsync] -
frame[FrameInfoIndex::IssueDrawCommandsStart];
@@ -219,7 +219,7 @@
void JankTracker::dumpFrames(int fd) {
dprintf(fd, "\n\n---PROFILEDATA---\n");
for (size_t i = 0; i < static_cast<size_t>(FrameInfoIndex::NumIndexes); i++) {
- dprintf(fd, "%s", FrameInfoNames[i].c_str());
+ dprintf(fd, "%s", FrameInfoNames[i]);
dprintf(fd, ",");
}
for (size_t i = 0; i < mFrames.size(); i++) {
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index df66981..f24ba5c 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -240,8 +240,8 @@
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
- "Mismatched size expectations, given %d expected %d",
- frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
+ "Mismatched size expectations, given %d expected %zu", frameInfoSize,
+ UI_THREAD_FRAME_INFO_SIZE);
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
return proxy->syncAndDrawFrame();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b760db2..f69ddac 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -484,7 +484,8 @@
// TODO(b/165985262): measure performance impact
const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
if (vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) {
- const auto inputEventId = mCurrentFrameInfo->get(FrameInfoIndex::NewestInputEvent);
+ const auto inputEventId =
+ static_cast<int32_t>(mCurrentFrameInfo->get(FrameInfoIndex::InputEventId));
native_window_set_frame_timeline_info(mNativeSurface->getNativeWindow(), vsyncId,
inputEventId);
}
@@ -591,7 +592,6 @@
}
void CanvasContext::finishFrame(FrameInfo* frameInfo) {
-
// TODO (b/169858044): Consolidate this into a single call.
mJankTracker.finishFrame(*frameInfo);
mJankTracker.finishGpuDraw(*frameInfo);
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
index ab23448..1a3dbe7 100644
--- a/libs/hwui/tests/unit/TypefaceTests.cpp
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -33,7 +33,7 @@
constexpr char kRobotoVariable[] = "/system/fonts/Roboto-Regular.ttf";
-constexpr char kRegularFont[] = "/system/fonts/NotoSerif-Regular.ttf";
+constexpr char kRegularFont[] = "/system/fonts/NotoSerif.ttf";
constexpr char kBoldFont[] = "/system/fonts/NotoSerif-Bold.ttf";
constexpr char kItalicFont[] = "/system/fonts/NotoSerif-Italic.ttf";
constexpr char kBoldItalicFont[] = "/system/fonts/NotoSerif-BoldItalic.ttf";
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 5e39660..38b48e9 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -117,7 +117,8 @@
boolean isLocationEnabledForUser(int userId);
void setLocationEnabledForUser(boolean enabled, int userId);
- void addTestProvider(String name, in ProviderProperties properties, String packageName, @nullable String attributionTag);
+ void addTestProvider(String name, in ProviderProperties properties,
+ in List<String> locationTags, String packageName, @nullable String attributionTag);
void removeTestProvider(String provider, String packageName, @nullable String attributionTag);
void setTestProviderLocation(String provider, in Location location, String packageName, @nullable String attributionTag);
void setTestProviderEnabled(String provider, boolean enabled, String packageName, @nullable String attributionTag);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 562b2e3..95bae5a 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -51,7 +51,7 @@
import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.location.provider.ProviderRequest;
-import android.location.provider.ProviderRequest.Listener;
+import android.location.provider.ProviderRequest.ChangedListener;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -76,6 +76,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -1957,12 +1958,32 @@
* allowed} for your app.
*/
public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties) {
+ addTestProvider(provider, properties, Collections.emptySet());
+ }
+
+ /**
+ * Creates a test location provider and adds it to the set of active providers. This provider
+ * will replace any provider with the same name that exists prior to this call.
+ *
+ * @param provider the provider name
+ * @param properties the provider properties
+ * @param locationTags the attribution tags for accessing location from the provider
+ *
+ * @throws IllegalArgumentException if provider is null
+ * @throws IllegalArgumentException if properties is null
+ * @throws SecurityException if {@link android.app.AppOpsManager#OPSTR_MOCK_LOCATION
+ * mock location app op} is not set to {@link android.app.AppOpsManager#MODE_ALLOWED
+ * allowed} for your app.
+ */
+ public void addTestProvider(@NonNull String provider, @NonNull ProviderProperties properties,
+ @NonNull Set<String> locationTags) {
Preconditions.checkArgument(provider != null, "invalid null provider");
Preconditions.checkArgument(properties != null, "invalid null properties");
+ Preconditions.checkArgument(locationTags != null, "invalid null location tags");
try {
- mService.addTestProvider(provider, properties, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mService.addTestProvider(provider, properties, new ArrayList<>(locationTags),
+ mContext.getOpPackageName(), mContext.getFeatureId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2779,33 +2800,32 @@
}
/**
- * Registers a {@link ProviderRequest.Listener} to all providers.
+ * Adds a {@link ProviderRequest.ChangedListener} for listening to all providers'
+ * {@link ProviderRequest} changed events.
*
* @param executor the executor that the callback runs on
* @param listener the listener to register
- * @return {@code true} always
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
- public boolean registerProviderRequestListener(
+ public void addProviderRequestChangedListener(
@NonNull @CallbackExecutor Executor executor,
- @NonNull Listener listener) {
+ @NonNull ChangedListener listener) {
ProviderRequestLazyLoader.sProviderRequestListeners.addListener(listener,
new ProviderRequestTransport(executor, listener));
- return true;
}
/**
- * Unregisters a {@link ProviderRequest.Listener}.
+ * Removes a {@link ProviderRequest.ChangedListener} that has been added.
*
* @param listener the listener to remove.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
- public void unregisterProviderRequestListener(
- @NonNull Listener listener) {
+ public void removeProviderRequestChangedListener(
+ @NonNull ProviderRequest.ChangedListener listener) {
ProviderRequestLazyLoader.sProviderRequestListeners.removeListener(listener);
}
@@ -3446,13 +3466,13 @@
}
private static class ProviderRequestTransport extends IProviderRequestListener.Stub
- implements ListenerTransport<ProviderRequest.Listener> {
+ implements ListenerTransport<ChangedListener> {
private final Executor mExecutor;
- private volatile @Nullable ProviderRequest.Listener mListener;
+ private volatile @Nullable ProviderRequest.ChangedListener mListener;
- ProviderRequestTransport(Executor executor, ProviderRequest.Listener listener) {
+ ProviderRequestTransport(Executor executor, ChangedListener listener) {
Preconditions.checkArgument(executor != null, "invalid null executor");
Preconditions.checkArgument(listener != null, "invalid null callback");
mExecutor = executor;
@@ -3465,7 +3485,7 @@
}
@Override
- public @Nullable ProviderRequest.Listener getListener() {
+ public @Nullable ProviderRequest.ChangedListener getListener() {
return mListener;
}
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
index a6a0e7a..763835c 100644
--- a/location/java/android/location/LocationManagerInternal.java
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -21,6 +21,10 @@
import android.annotation.Nullable;
import android.location.util.identity.CallerIdentity;
+import com.android.internal.annotations.Immutable;
+
+import java.util.Set;
+
/**
* Location manager local system service interface.
*
@@ -39,6 +43,21 @@
}
/**
+ * Interface for getting callbacks when a location provider's location tags change.
+ *
+ * @see LocationTagInfo
+ */
+ public interface OnProviderLocationTagsChangeListener {
+
+ /**
+ * Called when the location tags for a provider change.
+ *
+ * @param providerLocationTagInfo The tag info for a provider.
+ */
+ void onLocationTagsChanged(@NonNull LocationTagInfo providerLocationTagInfo);
+ }
+
+ /**
* Returns true if the given provider is enabled for the given user.
*
* @param provider A location provider as listed by {@link LocationManager#getAllProviders()}
@@ -88,4 +107,60 @@
* provider, and the elapsed nanos since boot the current time was computed at.
*/
public abstract @Nullable LocationTime getGnssTimeMillis();
+
+ /**
+ * Sets a listener for changes in the location providers' tags. Passing
+ * {@code null} clears the current listener.
+ *
+ * @param listener The listener.
+ */
+ public abstract void setOnProviderLocationTagsChangeListener(
+ @Nullable OnProviderLocationTagsChangeListener listener);
+
+ /**
+ * This class represents the location permission tags used by the location provider
+ * packages in a given UID. These tags are strictly used for accessing state guarded
+ * by the location permission(s) by a location provider which are required for the
+ * provider to fulfill its function as being a location provider.
+ */
+ @Immutable
+ public static class LocationTagInfo {
+ private final int mUid;
+
+ @NonNull
+ private final String mPackageName;
+
+ @Nullable
+ private final Set<String> mLocationTags;
+
+ public LocationTagInfo(int uid, @NonNull String packageName,
+ @Nullable Set<String> locationTags) {
+ mUid = uid;
+ mPackageName = packageName;
+ mLocationTags = locationTags;
+ }
+
+ /**
+ * @return The UID for which tags are related.
+ */
+ public int getUid() {
+ return mUid;
+ }
+
+ /**
+ * @return The package for which tags are related.
+ */
+ @NonNull
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * @return The tags for the package used for location related accesses.
+ */
+ @Nullable
+ public Set<String> getTags() {
+ return mLocationTags;
+ }
+ }
}
diff --git a/location/java/android/location/provider/ProviderRequest.java b/location/java/android/location/provider/ProviderRequest.java
index b6ec323..b72d365 100644
--- a/location/java/android/location/provider/ProviderRequest.java
+++ b/location/java/android/location/provider/ProviderRequest.java
@@ -56,10 +56,13 @@
/**
* Listener to be invoked when a new request is set to the provider.
*/
- public interface Listener {
+ public interface ChangedListener {
/**
* Invoked when a new request is set.
+ *
+ * @param provider the location provider associated with the request
+ * @param request the new {@link ProviderRequest}
*/
void onProviderRequestChanged(@NonNull String provider, @NonNull ProviderRequest request);
}
diff --git a/location/java/android/location/util/identity/CallerIdentity.java b/location/java/android/location/util/identity/CallerIdentity.java
index 0bb7dbb..85a083e 100644
--- a/location/java/android/location/util/identity/CallerIdentity.java
+++ b/location/java/android/location/util/identity/CallerIdentity.java
@@ -42,7 +42,16 @@
@VisibleForTesting
public static CallerIdentity forTest(int uid, int pid, String packageName,
@Nullable String attributionTag) {
- return new CallerIdentity(uid, pid, packageName, attributionTag, null);
+ return forTest(uid, pid, packageName, attributionTag, null);
+ }
+
+ /**
+ * Construct a CallerIdentity for test purposes.
+ */
+ @VisibleForTesting
+ public static CallerIdentity forTest(int uid, int pid, String packageName,
+ @Nullable String attributionTag, @Nullable String listenerId) {
+ return new CallerIdentity(uid, pid, packageName, attributionTag, listenerId);
}
/**
@@ -145,7 +154,10 @@
return mAttributionTag;
}
- /** The calling listener id. */
+ /**
+ * The calling listener id. A null listener id will match any other listener id for the purposes
+ * of {@link #equals(Object)}.
+ */
public String getListenerId() {
return mListenerId;
}
@@ -168,6 +180,17 @@
}
}
+ /**
+ * Returns a CallerIdentity corrosponding to this CallerIdentity but with a null listener id.
+ */
+ public CallerIdentity stripListenerId() {
+ if (mListenerId == null) {
+ return this;
+ } else {
+ return new CallerIdentity(mUid, mPid, mPackageName, mAttributionTag, null);
+ }
+ }
+
@Override
public String toString() {
int length = 10 + mPackageName.length();
@@ -201,15 +224,12 @@
return false;
}
CallerIdentity that = (CallerIdentity) o;
- return equalsIgnoringListenerId(that) && Objects.equals(mListenerId, that.mListenerId);
- }
-
- public boolean equalsIgnoringListenerId(CallerIdentity that) {
- return that != null
- && mUid == that.mUid
+ return mUid == that.mUid
&& mPid == that.mPid
&& mPackageName.equals(that.mPackageName)
- && Objects.equals(mAttributionTag, that.mAttributionTag);
+ && Objects.equals(mAttributionTag, that.mAttributionTag)
+ && (mListenerId == null || that.mListenerId == null || mListenerId.equals(
+ that.mListenerId));
}
@Override
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index c51c9dd..f3cee17 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.BIND_IMS_SERVICE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -91,6 +92,7 @@
import java.util.Set;
import java.util.UUID;
import java.util.Vector;
+import java.util.concurrent.Executor;
/**
@@ -2172,7 +2174,7 @@
mOnVideoSizeChangedListener = null;
mOnTimedTextListener = null;
mOnRtpRxNoticeListener = null;
- mOnRtpRxNoticeHandler = null;
+ mOnRtpRxNoticeExecutor = null;
synchronized (mTimeProviderLock) {
if (mTimeProvider != null) {
mTimeProvider.close();
@@ -3711,7 +3713,6 @@
case MEDIA_RTP_RX_NOTICE:
final OnRtpRxNoticeListener rtpRxNoticeListener = mOnRtpRxNoticeListener;
- final Handler rtpRxNoticeHandler = mOnRtpRxNoticeHandler;
if (rtpRxNoticeListener == null) {
return;
}
@@ -3730,14 +3731,9 @@
} finally {
parcel.recycle();
}
- if (rtpRxNoticeHandler == null) {
- rtpRxNoticeListener.onRtpRxNotice(mMediaPlayer, noticeType, data);
- } else {
- rtpRxNoticeHandler.post(
- () ->
- rtpRxNoticeListener
- .onRtpRxNotice(mMediaPlayer, noticeType, data));
- }
+ mOnRtpRxNoticeExecutor.execute(() ->
+ rtpRxNoticeListener
+ .onRtpRxNotice(mMediaPlayer, noticeType, data));
}
return;
@@ -4305,28 +4301,26 @@
*
* @see OnRtpRxNoticeListener
*
- * @param listener the listener called after a notice from RTP Rx
- * @param handler the {@link Handler} that receives RTP Tx events. If null is passed,
- * notifications will be posted on the thread that created this MediaPlayer
- * instance. If the creating thread does not have a {@link Looper}, then
- * notifications will be posted on the main thread.
+ * @param listener the listener called after a notice from RTP Rx.
+ * @param executor the {@link Executor} on which to post RTP Tx events.
* @hide
*/
@SystemApi
@RequiresPermission(BIND_IMS_SERVICE)
public void setOnRtpRxNoticeListener(
@NonNull Context context,
- @NonNull OnRtpRxNoticeListener listener, @Nullable Handler handler) {
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnRtpRxNoticeListener listener) {
Objects.requireNonNull(context);
Preconditions.checkArgument(
context.checkSelfPermission(BIND_IMS_SERVICE) == PERMISSION_GRANTED,
BIND_IMS_SERVICE + " permission not granted.");
mOnRtpRxNoticeListener = Objects.requireNonNull(listener);
- mOnRtpRxNoticeHandler = handler;
+ mOnRtpRxNoticeExecutor = Objects.requireNonNull(executor);
}
private OnRtpRxNoticeListener mOnRtpRxNoticeListener;
- private Handler mOnRtpRxNoticeHandler;
+ private Executor mOnRtpRxNoticeExecutor;
/**
* Register a callback to be invoked when a selected track has timed metadata available.
diff --git a/media/jni/android_media_JetPlayer.cpp b/media/jni/android_media_JetPlayer.cpp
index 481f80b..10a5b58 100644
--- a/media/jni/android_media_JetPlayer.cpp
+++ b/media/jni/android_media_JetPlayer.cpp
@@ -43,12 +43,34 @@
jfieldID nativePlayerInJavaObj; // stores in Java the native JetPlayer object
};
-static fields_t javaJetPlayerFields;
+static fields_t javaJetPlayerFields {};
+#define JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME "mNativePlayerInJavaObj"
+#define JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME "postEventFromNative"
+
+static void initializeJavaIDs(JNIEnv* env) {
+ static std::once_flag sJniInitialized;
+
+ std::call_once(sJniInitialized, [](JNIEnv* env) {
+ // Get the JetPlayer java class
+ jclass jetPlayerClass = FindClassOrDie(env, kClassPathName);
+ javaJetPlayerFields.jetClass = MakeGlobalRefOrDie(env, jetPlayerClass);
+
+ // Get the mNativePlayerInJavaObj variable field
+ javaJetPlayerFields.nativePlayerInJavaObj =
+ GetFieldIDOrDie(env, jetPlayerClass, JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME, "J");
+
+ // Get the callback to post events from this native code to Java
+ javaJetPlayerFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,
+ javaJetPlayerFields.jetClass, JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME,
+ "(Ljava/lang/Object;III)V");
+ }, env);
+}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
+
/*
* This function is called from JetPlayer instance's render thread
*/
@@ -79,6 +101,8 @@
android_media_JetPlayer_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jint maxTracks, jint trackBufferSize)
{
+ initializeJavaIDs(env);
+
//ALOGV("android_media_JetPlayer_setup(): entering.");
JetPlayer* lpJet = new JetPlayer(env->NewGlobalRef(weak_this), maxTracks, trackBufferSize);
@@ -511,28 +535,9 @@
{"native_clearQueue", "()Z", (void *)android_media_JetPlayer_clearQueue},
};
-#define JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME "mNativePlayerInJavaObj"
-#define JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME "postEventFromNative"
int register_android_media_JetPlayer(JNIEnv *env)
{
- javaJetPlayerFields.jetClass = NULL;
- javaJetPlayerFields.postNativeEventInJava = NULL;
- javaJetPlayerFields.nativePlayerInJavaObj = NULL;
-
- // Get the JetPlayer java class
- jclass jetPlayerClass = FindClassOrDie(env, kClassPathName);
- javaJetPlayerFields.jetClass = MakeGlobalRefOrDie(env, jetPlayerClass);
-
- // Get the mNativePlayerInJavaObj variable field
- javaJetPlayerFields.nativePlayerInJavaObj = GetFieldIDOrDie(env,
- jetPlayerClass, JAVA_NATIVEJETPLAYERINJAVAOBJ_FIELD_NAME, "J");
-
- // Get the callback to post events from this native code to Java
- javaJetPlayerFields.postNativeEventInJava = GetStaticMethodIDOrDie(env,
- javaJetPlayerFields.jetClass, JAVA_NATIVEJETPOSTEVENT_CALLBACK_NAME,
- "(Ljava/lang/Object;III)V");
-
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index 517672e..f491be8 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -202,10 +202,11 @@
uuid = NULL;
if (err != OK) {
- jniThrowException(
+ std::string strerr(StrCryptoError(err));
+ jniThrowExceptionFmt(
env,
"android/media/MediaCryptoException",
- "Failed to instantiate crypto object.");
+ "Failed to instantiate crypto object: %s", strerr.c_str());
return;
}
@@ -295,7 +296,8 @@
} else if (err == NO_INIT) {
msg += ": crypto plugin not initialized";
} else {
- msg.appendFormat(": general failure (%d)", err);
+ std::string strerr(StrCryptoError(err));
+ msg.appendFormat(": general failure (%s)", strerr.c_str());
}
jniThrowException(env, "android/media/MediaCryptoException", msg.string());
}
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index eee9f1e..4ae6876 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -217,23 +217,34 @@
void LnbClientCallbackImpl::onEvent(const LnbEventType lnbEventType) {
ALOGD("LnbClientCallbackImpl::onEvent, type=%d", lnbEventType);
JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(
- mLnbObj,
- gFields.onLnbEventID,
- (jint)lnbEventType);
+ jobject lnb(env->NewLocalRef(mLnbObj));
+ if (!env->IsSameObject(lnb, nullptr)) {
+ env->CallVoidMethod(
+ lnb,
+ gFields.onLnbEventID,
+ (jint)lnbEventType);
+ } else {
+ ALOGE("LnbClientCallbackImpl::onEvent:"
+ "Lnb object has been freed. Ignoring callback.");
+ }
}
void LnbClientCallbackImpl::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
ALOGD("LnbClientCallbackImpl::onDiseqcMessage");
JNIEnv *env = AndroidRuntime::getJNIEnv();
- jbyteArray array = env->NewByteArray(diseqcMessage.size());
- env->SetByteArrayRegion(
- array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
-
- env->CallVoidMethod(
- mLnbObj,
- gFields.onLnbDiseqcMessageID,
- array);
+ jobject lnb(env->NewLocalRef(mLnbObj));
+ if (!env->IsSameObject(lnb, nullptr)) {
+ jbyteArray array = env->NewByteArray(diseqcMessage.size());
+ env->SetByteArrayRegion(
+ array, 0, diseqcMessage.size(), reinterpret_cast<jbyte*>(diseqcMessage[0]));
+ env->CallVoidMethod(
+ lnb,
+ gFields.onLnbDiseqcMessageID,
+ array);
+ } else {
+ ALOGE("LnbClientCallbackImpl::onDiseqcMessage:"
+ "Lnb object has been freed. Ignoring callback.");
+ }
}
void LnbClientCallbackImpl::setLnb(jweak lnbObj) {
@@ -254,19 +265,31 @@
void DvrClientCallbackImpl::onRecordStatus(RecordStatus status) {
ALOGD("DvrClientCallbackImpl::onRecordStatus");
JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(
- mDvrObj,
- gFields.onDvrRecordStatusID,
- (jint) status);
+ jobject dvr(env->NewLocalRef(mDvrObj));
+ if (!env->IsSameObject(dvr, nullptr)) {
+ env->CallVoidMethod(
+ dvr,
+ gFields.onDvrRecordStatusID,
+ (jint) status);
+ } else {
+ ALOGE("DvrClientCallbackImpl::onRecordStatus:"
+ "Dvr object has been freed. Ignoring callback.");
+ }
}
void DvrClientCallbackImpl::onPlaybackStatus(PlaybackStatus status) {
ALOGD("DvrClientCallbackImpl::onPlaybackStatus");
JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(
- mDvrObj,
- gFields.onDvrPlaybackStatusID,
- (jint) status);
+ jobject dvr(env->NewLocalRef(mDvrObj));
+ if (!env->IsSameObject(dvr, nullptr)) {
+ env->CallVoidMethod(
+ dvr,
+ gFields.onDvrPlaybackStatusID,
+ (jint) status);
+ } else {
+ ALOGE("DvrClientCallbackImpl::onPlaybackStatus:"
+ "Dvr object has been freed. Ignoring callback.");
+ }
}
void DvrClientCallbackImpl::setDvr(jweak dvrObj) {
@@ -810,10 +833,16 @@
}
}
}
- env->CallVoidMethod(
- mFilterObj,
- gFields.onFilterEventID,
- array);
+ jobject filter(env->NewLocalRef(mFilterObj));
+ if (!env->IsSameObject(filter, nullptr)) {
+ env->CallVoidMethod(
+ filter,
+ gFields.onFilterEventID,
+ array);
+ } else {
+ ALOGE("FilterClientCallbackImpl::onFilterEvent_1_1:"
+ "Filter object has been freed. Ignoring callback.");
+ }
}
void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent) {
@@ -828,10 +857,16 @@
void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
ALOGD("FilterClientCallbackImpl::onFilterStatus");
JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(
- mFilterObj,
- gFields.onFilterStatusID,
- (jint)status);
+ jobject filter(env->NewLocalRef(mFilterObj));
+ if (!env->IsSameObject(filter, nullptr)) {
+ env->CallVoidMethod(
+ filter,
+ gFields.onFilterStatusID,
+ (jint)status);
+ } else {
+ ALOGE("FilterClientCallbackImpl::onFilterStatus:"
+ "Filter object has been freed. Ignoring callback.");
+ }
}
void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) {
@@ -841,6 +876,15 @@
mFilterClient = filterClient;
}
+FilterClientCallbackImpl::~FilterClientCallbackImpl() {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ if (mFilterObj != NULL) {
+ env->DeleteWeakGlobalRef(mFilterObj);
+ mFilterObj = NULL;
+ }
+ mFilterClient = NULL;
+}
+
/////////////// FrontendClientCallbackImpl ///////////////////////
FrontendClientCallbackImpl::FrontendClientCallbackImpl(jweak tunerObj) : mObject(tunerObj) {}
@@ -848,10 +892,16 @@
void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
ALOGD("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(
- mObject,
- gFields.onFrontendEventID,
- (jint)frontendEventType);
+ jobject frontend(env->NewLocalRef(mObject));
+ if (!env->IsSameObject(frontend, nullptr)) {
+ env->CallVoidMethod(
+ frontend,
+ gFields.onFrontendEventID,
+ (jint)frontendEventType);
+ } else {
+ ALOGE("FrontendClientCallbackImpl::onEvent:"
+ "Frontend object has been freed. Ignoring callback.");
+ }
}
void FrontendClientCallbackImpl::onScanMessage(
@@ -859,11 +909,17 @@
ALOGD("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
+ jobject frontend(env->NewLocalRef(mObject));
+ if (env->IsSameObject(frontend, nullptr)) {
+ ALOGE("FrontendClientCallbackImpl::onScanMessage:"
+ "Frontend object has been freed. Ignoring callback.");
+ return;
+ }
switch(type) {
case FrontendScanMessageType::LOCKED: {
if (message.isLocked()) {
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onLocked", "()V"));
}
break;
@@ -871,14 +927,14 @@
case FrontendScanMessageType::END: {
if (message.isEnd()) {
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onScanStopped", "()V"));
}
break;
}
case FrontendScanMessageType::PROGRESS_PERCENT: {
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onProgress", "(I)V"),
(jint) message.progressPercent());
break;
@@ -889,7 +945,7 @@
env->SetIntArrayRegion(freqs, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onFrequenciesReport", "([I)V"),
freqs);
break;
@@ -900,21 +956,21 @@
env->SetIntArrayRegion(symbolRates, 0, v.size(), reinterpret_cast<jint*>(&v[0]));
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onSymbolRates", "([I)V"),
symbolRates);
break;
}
case FrontendScanMessageType::HIERARCHY: {
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onHierarchy", "(I)V"),
(jint) message.hierarchy());
break;
}
case FrontendScanMessageType::ANALOG_TYPE: {
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onSignalType", "(I)V"),
(jint) message.analogType());
break;
@@ -926,7 +982,7 @@
env->SetIntArrayRegion(plpIds, 0, jintV.size(), &jintV[0]);
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onPlpIds", "([I)V"),
plpIds);
break;
@@ -938,7 +994,7 @@
env->SetIntArrayRegion(groupIds, 0, jintV.size(), &jintV[0]);
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onGroupIds", "([I)V"),
groupIds);
break;
@@ -950,7 +1006,7 @@
env->SetIntArrayRegion(streamIds, 0, jintV.size(), &jintV[0]);
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onInputStreamIds", "([I)V"),
streamIds);
break;
@@ -961,21 +1017,21 @@
if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sStd) {
standard = (jint) std.sStd();
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
standard);
} else if (std.getDiscriminator() ==
FrontendScanMessage::Standard::hidl_discriminator::tStd) {
standard = (jint) std.tStd();
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
standard);
} else if (std.getDiscriminator() ==
FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
standard = (jint) std.sifStd();
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onAnalogSifStandard", "(I)V"),
standard);
}
@@ -996,7 +1052,7 @@
env->SetObjectArrayElement(array, i, obj);
}
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onAtsc3PlpInfos",
"([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
array);
@@ -1010,6 +1066,12 @@
ALOGD("FrontendClientCallbackImpl::onScanMessageExt1_1, type=%d", type);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
+ jobject frontend(env->NewLocalRef(mObject));
+ if (env->IsSameObject(frontend, nullptr)) {
+ ALOGE("FrontendClientCallbackImpl::onScanMessageExt1_1:"
+ "Frontend object has been freed. Ignoring callback.");
+ return;
+ }
switch(type) {
case FrontendScanMessageTypeExt1_1::MODULATION: {
jint modulation = -1;
@@ -1056,7 +1118,7 @@
}
if (modulation > 0) {
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onModulationReported", "(I)V"),
modulation);
}
@@ -1065,7 +1127,7 @@
case FrontendScanMessageTypeExt1_1::HIGH_PRIORITY: {
bool isHighPriority = message.isHighPriority();
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onPriorityReported", "(B)V"),
isHighPriority);
break;
@@ -1073,7 +1135,7 @@
case FrontendScanMessageTypeExt1_1::DVBC_ANNEX: {
jint dvbcAnnex = (jint) message.annex();
env->CallVoidMethod(
- mObject,
+ frontend,
env->GetMethodID(clazz, "onDvbcAnnexReported", "(I)V"),
dvbcAnnex);
break;
@@ -1083,6 +1145,14 @@
}
}
+FrontendClientCallbackImpl::~FrontendClientCallbackImpl() {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ if (mObject != NULL) {
+ env->DeleteWeakGlobalRef(mObject);
+ mObject = NULL;
+ }
+}
+
/////////////// Tuner ///////////////////////
sp<TunerClient> JTuner::mTunerClient;
@@ -1158,15 +1228,22 @@
if (mDemuxClient != NULL) {
mDemuxClient->setFrontendDataSource(mFeClient);
}
- sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject);
- mFeClient->setCallback(feClientCb);
JNIEnv *env = AndroidRuntime::getJNIEnv();
+ jobject tuner(env->NewLocalRef(mObject));
+ if (env->IsSameObject(tuner, nullptr)) {
+ ALOGE("openFrontendByHandle"
+ "Tuner object has been freed. Failed to open frontend.");
+ return NULL;
+ }
+
+ sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject);
+ mFeClient->setCallback(feClientCb);
// TODO: add more fields to frontend
return env->NewObject(
env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
gFields.frontendInitID,
- mObject,
+ tuner,
(jint) mFeId);
}
@@ -1714,16 +1791,14 @@
dvrObj =
env->NewObject(
env->FindClass("android/media/tv/tuner/dvr/DvrRecorder"),
- gFields.dvrRecorderInitID,
- mObject);
+ gFields.dvrRecorderInitID);
dvrClient->incStrong(dvrObj);
env->SetLongField(dvrObj, gFields.dvrRecorderContext, (jlong)dvrClient.get());
} else {
dvrObj =
env->NewObject(
env->FindClass("android/media/tv/tuner/dvr/DvrPlayback"),
- gFields.dvrPlaybackInitID,
- mObject);
+ gFields.dvrPlaybackInitID);
dvrClient->incStrong(dvrObj);
env->SetLongField(dvrObj, gFields.dvrPlaybackContext, (jlong)dvrClient.get());
}
@@ -2126,6 +2201,10 @@
intBandwidth = static_cast<jint>(bandwidth.dvbt());
break;
}
+ case FrontendBandwidth::hidl_discriminator::dvbc: {
+ intBandwidth = static_cast<jint>(bandwidth.dvbc());
+ break;
+ }
case FrontendBandwidth::hidl_discriminator::isdbt: {
intBandwidth = static_cast<jint>(bandwidth.isdbt());
break;
@@ -2646,12 +2725,10 @@
FrontendDvbsVcmMode vcmMode =
static_cast<FrontendDvbsVcmMode>(
env->GetIntField(settings, env->GetFieldID(clazz, "mVcmMode", "I")));
- FrontendDvbsCodeRate coderate = getDvbsCodeRate(env, settings);
FrontendDvbsSettings frontendDvbsSettings {
.frequency = freq,
.modulation = modulation,
- .coderate = coderate,
.symbolRate = symbolRate,
.rolloff = rolloff,
.pilot = pilot,
@@ -2659,6 +2736,13 @@
.standard = standard,
.vcmMode = vcmMode,
};
+
+ jobject jcodeRate = env->GetObjectField(settings, env->GetFieldID(clazz, "mCodeRate",
+ "Landroid/media/tv/tuner/frontend/DvbsCodeRate;"));
+ if (jcodeRate != NULL) {
+ frontendDvbsSettings.coderate = getDvbsCodeRate(env, settings);
+ }
+
frontendSettings.dvbs(frontendDvbsSettings);
return frontendSettings;
}
@@ -2670,7 +2754,7 @@
static_cast<FrontendDvbsScanType>(
env->GetIntField(settings, env->GetFieldID(clazz, "mScanType", "I")));
bool isDiseqcRxMessage = static_cast<bool>(env->GetBooleanField(
- settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "B")));
+ settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "Z")));
FrontendDvbsSettingsExt1_1 dvbsExt1_1 {
.scanType = scanType,
@@ -2910,6 +2994,10 @@
static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
ALOGD("getFrontendSettings %d", type);
+ if (type == static_cast<int>(::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) {
+ return FrontendSettings();
+ }
+
FrontendType feType = static_cast<FrontendType>(type);
switch(feType) {
case FrontendType::ANALOG:
@@ -3483,26 +3571,28 @@
.tpid = tpid,
};
- DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype);
- switch (tsType) {
- case DemuxTsFilterType::SECTION:
- tsFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
- break;
- case DemuxTsFilterType::AUDIO:
- case DemuxTsFilterType::VIDEO:
- tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
- break;
- case DemuxTsFilterType::PES:
- tsFilterSettings.filterSettings.pesData(
- getFilterPesDataSettings(env, settingsObj));
- break;
- case DemuxTsFilterType::RECORD:
- tsFilterSettings.filterSettings.record(
- getFilterRecordSettings(env, settingsObj));
- break;
- default:
- break;
+ if (settingsObj != NULL) {
+ DemuxTsFilterType tsType = static_cast<DemuxTsFilterType>(subtype);
+ switch (tsType) {
+ case DemuxTsFilterType::SECTION:
+ tsFilterSettings.filterSettings.section(
+ getFilterSectionSettings(env, settingsObj));
+ break;
+ case DemuxTsFilterType::AUDIO:
+ case DemuxTsFilterType::VIDEO:
+ tsFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
+ break;
+ case DemuxTsFilterType::PES:
+ tsFilterSettings.filterSettings.pesData(
+ getFilterPesDataSettings(env, settingsObj));
+ break;
+ case DemuxTsFilterType::RECORD:
+ tsFilterSettings.filterSettings.record(
+ getFilterRecordSettings(env, settingsObj));
+ break;
+ default:
+ break;
+ }
}
filterSettings.ts(tsFilterSettings);
break;
@@ -3514,60 +3604,55 @@
DemuxMmtpFilterSettings mmtpFilterSettings {
.mmtpPid = mmtpPid,
};
- DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype);
- switch (mmtpType) {
- case DemuxMmtpFilterType::SECTION:
- mmtpFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
- break;
- case DemuxMmtpFilterType::AUDIO:
- case DemuxMmtpFilterType::VIDEO:
- mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
- break;
- case DemuxMmtpFilterType::PES:
- mmtpFilterSettings.filterSettings.pesData(
- getFilterPesDataSettings(env, settingsObj));
- break;
- case DemuxMmtpFilterType::RECORD:
- mmtpFilterSettings.filterSettings.record(
- getFilterRecordSettings(env, settingsObj));
- break;
- case DemuxMmtpFilterType::DOWNLOAD:
- mmtpFilterSettings.filterSettings.download(
- getFilterDownloadSettings(env, settingsObj));
- break;
- default:
- break;
+
+ if (settingsObj != NULL) {
+ DemuxMmtpFilterType mmtpType = static_cast<DemuxMmtpFilterType>(subtype);
+ switch (mmtpType) {
+ case DemuxMmtpFilterType::SECTION:
+ mmtpFilterSettings.filterSettings.section(
+ getFilterSectionSettings(env, settingsObj));
+ break;
+ case DemuxMmtpFilterType::AUDIO:
+ case DemuxMmtpFilterType::VIDEO:
+ mmtpFilterSettings.filterSettings.av(getFilterAvSettings(env, settingsObj));
+ break;
+ case DemuxMmtpFilterType::PES:
+ mmtpFilterSettings.filterSettings.pesData(
+ getFilterPesDataSettings(env, settingsObj));
+ break;
+ case DemuxMmtpFilterType::RECORD:
+ mmtpFilterSettings.filterSettings.record(
+ getFilterRecordSettings(env, settingsObj));
+ break;
+ case DemuxMmtpFilterType::DOWNLOAD:
+ mmtpFilterSettings.filterSettings.download(
+ getFilterDownloadSettings(env, settingsObj));
+ break;
+ default:
+ break;
+ }
}
filterSettings.mmtp(mmtpFilterSettings);
break;
}
case DemuxFilterMainType::IP: {
DemuxIpAddress ipAddr = getDemuxIpAddress(env, filterConfigObj);
-
DemuxIpFilterSettings ipFilterSettings {
.ipAddr = ipAddr,
};
+
DemuxIpFilterType ipType = static_cast<DemuxIpFilterType>(subtype);
- switch (ipType) {
- case DemuxIpFilterType::SECTION: {
- ipFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
- break;
- }
- case DemuxIpFilterType::IP: {
- jclass clazz = env->FindClass(
- "android/media/tv/tuner/filter/IpFilterConfiguration");
- bool bPassthrough = static_cast<bool>(
- env->GetBooleanField(
- filterConfigObj, env->GetFieldID(
- clazz, "mPassthrough", "Z")));
- ipFilterSettings.filterSettings.bPassthrough(bPassthrough);
- break;
- }
- default: {
- break;
- }
+ if (ipType == DemuxIpFilterType::SECTION && settingsObj != NULL) {
+ ipFilterSettings.filterSettings.section(
+ getFilterSectionSettings(env, settingsObj));
+ } else if (ipType == DemuxIpFilterType::IP) {
+ jclass clazz = env->FindClass(
+ "android/media/tv/tuner/filter/IpFilterConfiguration");
+ bool bPassthrough = static_cast<bool>(
+ env->GetBooleanField(
+ filterConfigObj, env->GetFieldID(
+ clazz, "mPassthrough", "Z")));
+ ipFilterSettings.filterSettings.bPassthrough(bPassthrough);
}
filterSettings.ip(ipFilterSettings);
break;
@@ -3584,24 +3669,17 @@
.packetType = packetType,
.isCompressedIpPacket = isCompressedIpPacket,
};
+
DemuxTlvFilterType tlvType = static_cast<DemuxTlvFilterType>(subtype);
- switch (tlvType) {
- case DemuxTlvFilterType::SECTION: {
- tlvFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
- break;
- }
- case DemuxTlvFilterType::TLV: {
- bool bPassthrough = static_cast<bool>(
- env->GetBooleanField(
- filterConfigObj, env->GetFieldID(
- clazz, "mPassthrough", "Z")));
- tlvFilterSettings.filterSettings.bPassthrough(bPassthrough);
- break;
- }
- default: {
- break;
- }
+ if (tlvType == DemuxTlvFilterType::SECTION && settingsObj != NULL) {
+ tlvFilterSettings.filterSettings.section(
+ getFilterSectionSettings(env, settingsObj));
+ } else if (tlvType == DemuxTlvFilterType::TLV) {
+ bool bPassthrough = static_cast<bool>(
+ env->GetBooleanField(
+ filterConfigObj, env->GetFieldID(
+ clazz, "mPassthrough", "Z")));
+ tlvFilterSettings.filterSettings.bPassthrough(bPassthrough);
}
filterSettings.tlv(tlvFilterSettings);
break;
@@ -3616,14 +3694,17 @@
.packetType = packetType,
.lengthType = lengthType,
};
- DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype);
- switch (alpType) {
- case DemuxAlpFilterType::SECTION:
- alpFilterSettings.filterSettings.section(
- getFilterSectionSettings(env, settingsObj));
- break;
- default:
- break;
+
+ if (settingsObj != NULL) {
+ DemuxAlpFilterType alpType = static_cast<DemuxAlpFilterType>(subtype);
+ switch (alpType) {
+ case DemuxAlpFilterType::SECTION:
+ alpFilterSettings.filterSettings.section(
+ getFilterSectionSettings(env, settingsObj));
+ break;
+ default:
+ break;
+ }
}
filterSettings.alp(alpFilterSettings);
break;
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 0e30b18e..fafef42 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -118,6 +118,7 @@
};
struct FilterClientCallbackImpl : public FilterClientCallback {
+ ~FilterClientCallbackImpl();
virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
const DemuxFilterEventExt& filterEventExt);
virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
@@ -155,7 +156,7 @@
struct FrontendClientCallbackImpl : public FrontendClientCallback {
FrontendClientCallbackImpl(jweak tunerObj);
-
+ ~FrontendClientCallbackImpl();
virtual void onEvent(FrontendEventType frontendEventType);
virtual void onScanMessage(
FrontendScanMessageType type, const FrontendScanMessage& message);
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 4efdcac..ffed474 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -32,6 +32,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
+#include "core_jni_helpers.h"
#include <jni.h>
#include <media/stagefright/NuMediaExtractor.h>
#include <nativehelper/JNIHelp.h>
@@ -48,6 +49,7 @@
// ----------------------------------------------------------------------------
+// MtpDatabase methods
static jmethodID method_beginSendObject;
static jmethodID method_endSendObject;
static jmethodID method_rescanFile;
@@ -75,6 +77,7 @@
static jmethodID method_getObjectReferences;
static jmethodID method_setObjectReferences;
+// MtpDatabase fields.
static jfieldID field_context;
// MtpPropertyList methods
@@ -86,6 +89,59 @@
static jmethodID method_getLongValues;
static jmethodID method_getStringValues;
+// Initializer for the jfieldIDs and jmethodIDs above. This method must be invoked
+// before using these static fields and methods for JNI accesses.
+static void initializeJavaIDs(JNIEnv* env) {
+ static std::once_flag sJniInitialized;
+
+#define GET_METHOD_ID(name, jclass, signature) \
+ method_##name = GetMethodIDOrDie(env, jclass, #name, signature);
+
+ std::call_once(sJniInitialized, [](JNIEnv* env) {
+ const jclass mdb_class = FindClassOrDie(env, "android/mtp/MtpDatabase");
+ GET_METHOD_ID(beginSendObject, mdb_class, "(Ljava/lang/String;III)I");
+ GET_METHOD_ID(endSendObject, mdb_class, "(IZ)V");
+ GET_METHOD_ID(rescanFile, mdb_class, "(Ljava/lang/String;II)V");
+ GET_METHOD_ID(getObjectList, mdb_class, "(III)[I");
+ GET_METHOD_ID(getNumObjects, mdb_class, "(III)I");
+ GET_METHOD_ID(getSupportedPlaybackFormats, mdb_class, "()[I");
+ GET_METHOD_ID(getSupportedCaptureFormats, mdb_class, "()[I");
+ GET_METHOD_ID(getSupportedObjectProperties, mdb_class, "(I)[I");
+ GET_METHOD_ID(getSupportedDeviceProperties, mdb_class, "()[I");
+ GET_METHOD_ID(setObjectProperty, mdb_class, "(IIJLjava/lang/String;)I");
+ GET_METHOD_ID(getDeviceProperty, mdb_class, "(I[J[C)I");
+ GET_METHOD_ID(setDeviceProperty, mdb_class, "(IJLjava/lang/String;)I");
+ GET_METHOD_ID(getObjectPropertyList, mdb_class, "(IIIII)Landroid/mtp/MtpPropertyList;");
+ GET_METHOD_ID(getObjectInfo, mdb_class, "(I[I[C[J)Z");
+ GET_METHOD_ID(getObjectFilePath, mdb_class, "(I[C[J)I");
+ GET_METHOD_ID(openFilePath, mdb_class, "(Ljava/lang/String;Z)I");
+ GET_METHOD_ID(getThumbnailInfo, mdb_class, "(I[J)Z");
+ GET_METHOD_ID(getThumbnailData, mdb_class, "(I)[B");
+ GET_METHOD_ID(beginDeleteObject, mdb_class, "(I)I");
+ GET_METHOD_ID(endDeleteObject, mdb_class, "(IZ)V");
+ GET_METHOD_ID(beginMoveObject, mdb_class, "(III)I");
+ GET_METHOD_ID(endMoveObject, mdb_class, "(IIIIIZ)V");
+ GET_METHOD_ID(beginCopyObject, mdb_class, "(III)I");
+ GET_METHOD_ID(endCopyObject, mdb_class, "(IZ)V");
+ GET_METHOD_ID(getObjectReferences, mdb_class, "(I)[I");
+ GET_METHOD_ID(setObjectReferences, mdb_class, "(I[I)I");
+ field_context = GetFieldIDOrDie(env, mdb_class, "mNativeContext", "J");
+
+ const jclass mpl_class = FindClassOrDie(env, "android/mtp/MtpPropertyList");
+ GET_METHOD_ID(getCode, mpl_class, "()I");
+ GET_METHOD_ID(getCount, mpl_class, "()I");
+ GET_METHOD_ID(getObjectHandles, mpl_class, "()[I");
+ GET_METHOD_ID(getPropertyCodes, mpl_class, "()[I");
+ GET_METHOD_ID(getDataTypes, mpl_class, "()[I");
+ GET_METHOD_ID(getLongValues, mpl_class, "()[J");
+ GET_METHOD_ID(getStringValues, mpl_class, "()[Ljava/lang/String;");
+
+ return 0;
+ }, env);
+
+#undef GET_METHOD_ID
+}
+
IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
return (IMtpDatabase *)env->GetLongField(database, field_context);
@@ -1280,6 +1336,7 @@
static void
android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
{
+ initializeJavaIDs(env);
MtpDatabase* database = new MtpDatabase(env, thiz);
env->SetLongField(thiz, field_context, (jlong)database);
checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -1314,69 +1371,9 @@
{"format_date_time", "(J)Ljava/lang/String;",
(void *)android_mtp_MtpPropertyGroup_format_date_time},
};
-
-#define GET_METHOD_ID(name, jclass, signature) \
- method_##name = env->GetMethodID(jclass, #name, signature); \
- if (method_##name == NULL) { \
- ALOGE("Can't find " #name); \
- return -1; \
- } \
-
+ \
int register_android_mtp_MtpDatabase(JNIEnv *env)
{
- jclass clazz;
-
- clazz = env->FindClass("android/mtp/MtpDatabase");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpDatabase");
- return -1;
- }
- GET_METHOD_ID(beginSendObject, clazz, "(Ljava/lang/String;III)I");
- GET_METHOD_ID(endSendObject, clazz, "(IZ)V");
- GET_METHOD_ID(rescanFile, clazz, "(Ljava/lang/String;II)V");
- GET_METHOD_ID(getObjectList, clazz, "(III)[I");
- GET_METHOD_ID(getNumObjects, clazz, "(III)I");
- GET_METHOD_ID(getSupportedPlaybackFormats, clazz, "()[I");
- GET_METHOD_ID(getSupportedCaptureFormats, clazz, "()[I");
- GET_METHOD_ID(getSupportedObjectProperties, clazz, "(I)[I");
- GET_METHOD_ID(getSupportedDeviceProperties, clazz, "()[I");
- GET_METHOD_ID(setObjectProperty, clazz, "(IIJLjava/lang/String;)I");
- GET_METHOD_ID(getDeviceProperty, clazz, "(I[J[C)I");
- GET_METHOD_ID(setDeviceProperty, clazz, "(IJLjava/lang/String;)I");
- GET_METHOD_ID(getObjectPropertyList, clazz, "(IIIII)Landroid/mtp/MtpPropertyList;");
- GET_METHOD_ID(getObjectInfo, clazz, "(I[I[C[J)Z");
- GET_METHOD_ID(getObjectFilePath, clazz, "(I[C[J)I");
- GET_METHOD_ID(openFilePath, clazz, "(Ljava/lang/String;Z)I");
- GET_METHOD_ID(getThumbnailInfo, clazz, "(I[J)Z");
- GET_METHOD_ID(getThumbnailData, clazz, "(I)[B");
- GET_METHOD_ID(beginDeleteObject, clazz, "(I)I");
- GET_METHOD_ID(endDeleteObject, clazz, "(IZ)V");
- GET_METHOD_ID(beginMoveObject, clazz, "(III)I");
- GET_METHOD_ID(endMoveObject, clazz, "(IIIIIZ)V");
- GET_METHOD_ID(beginCopyObject, clazz, "(III)I");
- GET_METHOD_ID(endCopyObject, clazz, "(IZ)V");
- GET_METHOD_ID(getObjectReferences, clazz, "(I)[I");
- GET_METHOD_ID(setObjectReferences, clazz, "(I[I)I");
-
- field_context = env->GetFieldID(clazz, "mNativeContext", "J");
- if (field_context == NULL) {
- ALOGE("Can't find MtpDatabase.mNativeContext");
- return -1;
- }
-
- clazz = env->FindClass("android/mtp/MtpPropertyList");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpPropertyList");
- return -1;
- }
- GET_METHOD_ID(getCode, clazz, "()I");
- GET_METHOD_ID(getCount, clazz, "()I");
- GET_METHOD_ID(getObjectHandles, clazz, "()[I");
- GET_METHOD_ID(getPropertyCodes, clazz, "()[I");
- GET_METHOD_ID(getDataTypes, clazz, "()[I");
- GET_METHOD_ID(getLongValues, clazz, "()[J");
- GET_METHOD_ID(getStringValues, clazz, "()[Ljava/lang/String;");
-
if (AndroidRuntime::registerNativeMethods(env,
"android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
return -1;
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 060eaf9..3d2b00fe 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -34,6 +34,7 @@
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
+#include "core_jni_helpers.h"
#include "nativehelper/ScopedLocalRef.h"
#include "private/android_filesystem_config.h"
@@ -107,6 +108,95 @@
static jfieldID field_event_parameter2;
static jfieldID field_event_parameter3;
+// Initializer for the jclasses, jfieldIDs and jmethodIDs declared above. This method must be
+// invoked before using these static fields for JNI accesses.
+static void initializeJavaIDs(JNIEnv* env) {
+ static std::once_flag sJniInitialized;
+
+ std::call_once(sJniInitialized, [](JNIEnv* env) {
+ clazz_deviceInfo =
+ (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpDeviceInfo"));
+ constructor_deviceInfo = GetMethodIDOrDie(env, clazz_deviceInfo, "<init>", "()V");
+ field_deviceInfo_manufacturer =
+ GetFieldIDOrDie(env, clazz_deviceInfo, "mManufacturer", "Ljava/lang/String;");
+ field_deviceInfo_model =
+ GetFieldIDOrDie(env, clazz_deviceInfo, "mModel", "Ljava/lang/String;");
+ field_deviceInfo_version =
+ GetFieldIDOrDie(env, clazz_deviceInfo, "mVersion", "Ljava/lang/String;");
+ field_deviceInfo_serialNumber =
+ GetFieldIDOrDie(env, clazz_deviceInfo, "mSerialNumber", "Ljava/lang/String;");
+ field_deviceInfo_operationsSupported =
+ GetFieldIDOrDie(env, clazz_deviceInfo, "mOperationsSupported", "[I");
+ field_deviceInfo_eventsSupported =
+ GetFieldIDOrDie(env, clazz_deviceInfo, "mEventsSupported", "[I");
+
+ clazz_storageInfo =
+ (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpStorageInfo"));
+ constructor_storageInfo = GetMethodIDOrDie(env, clazz_storageInfo, "<init>", "()V");
+ field_storageInfo_storageId = GetFieldIDOrDie(env, clazz_storageInfo, "mStorageId", "I");
+ field_storageInfo_maxCapacity =
+ GetFieldIDOrDie(env, clazz_storageInfo, "mMaxCapacity", "J");
+ field_storageInfo_freeSpace =
+ GetFieldIDOrDie(env, clazz_storageInfo, "mFreeSpace", "J");
+ field_storageInfo_description =
+ GetFieldIDOrDie(env, clazz_storageInfo, "mDescription", "Ljava/lang/String;");
+ field_storageInfo_volumeIdentifier =
+ GetFieldIDOrDie(env, clazz_storageInfo, "mVolumeIdentifier", "Ljava/lang/String;");
+
+ clazz_objectInfo =
+ (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpObjectInfo"));
+ constructor_objectInfo = GetMethodIDOrDie(env, clazz_objectInfo, "<init>", "()V");
+ field_objectInfo_handle = GetFieldIDOrDie(env, clazz_objectInfo, "mHandle", "I");
+ field_objectInfo_storageId = GetFieldIDOrDie(env, clazz_objectInfo, "mStorageId", "I");
+ field_objectInfo_format = GetFieldIDOrDie(env, clazz_objectInfo, "mFormat", "I");
+ field_objectInfo_protectionStatus =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mProtectionStatus", "I");
+ field_objectInfo_compressedSize =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mCompressedSize", "I");
+ field_objectInfo_thumbFormat = GetFieldIDOrDie(env, clazz_objectInfo, "mThumbFormat", "I");
+ field_objectInfo_thumbCompressedSize =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mThumbCompressedSize", "I");
+ field_objectInfo_thumbPixWidth =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mThumbPixWidth", "I");
+ field_objectInfo_thumbPixHeight =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mThumbPixHeight", "I");
+ field_objectInfo_imagePixWidth =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mImagePixWidth", "I");
+ field_objectInfo_imagePixHeight =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mImagePixHeight", "I");
+ field_objectInfo_imagePixDepth =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mImagePixDepth", "I");
+ field_objectInfo_parent = GetFieldIDOrDie(env, clazz_objectInfo, "mParent", "I");
+ field_objectInfo_associationType =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mAssociationType", "I");
+ field_objectInfo_associationDesc =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mAssociationDesc", "I");
+ field_objectInfo_sequenceNumber =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mSequenceNumber", "I");
+ field_objectInfo_name =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mName", "Ljava/lang/String;");
+ field_objectInfo_dateCreated = GetFieldIDOrDie(env, clazz_objectInfo, "mDateCreated", "J");
+ field_objectInfo_dateModified =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mDateModified", "J");
+ field_objectInfo_keywords =
+ GetFieldIDOrDie(env, clazz_objectInfo, "mKeywords", "Ljava/lang/String;");
+
+ clazz_event = (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/mtp/MtpEvent"));
+ constructor_event = GetMethodIDOrDie(env, clazz_event, "<init>", "()V");
+ field_event_eventCode = GetFieldIDOrDie(env, clazz_event, "mEventCode", "I");
+ field_event_parameter1 = GetFieldIDOrDie(env, clazz_event, "mParameter1", "I");
+ field_event_parameter2 = GetFieldIDOrDie(env, clazz_event, "mParameter2", "I");
+ field_event_parameter3 = GetFieldIDOrDie(env, clazz_event, "mParameter3", "I");
+
+ const jclass clazz = FindClassOrDie(env, "android/mtp/MtpDevice");
+ field_context = GetFieldIDOrDie(env, clazz, "mNativeContext", "J");
+
+ clazz_io_exception = (jclass)env->NewGlobalRef(FindClassOrDie(env, "java/io/IOException"));
+ clazz_operation_canceled_exception =
+ (jclass)env->NewGlobalRef(FindClassOrDie(env, "android/os/OperationCanceledException"));
+ }, env);
+}
+
class JavaArrayWriter {
public:
JavaArrayWriter(JNIEnv* env, jbyteArray array) :
@@ -132,6 +222,11 @@
MtpDevice* get_device_from_object(JNIEnv* env, jobject javaDevice)
{
+ // get_device_from_object() is called by the majority of JNI methods in this file. Call
+ // `initializeJavaIDs()` here to ensure JNI methodID's, fieldIDs and classes are initialized
+ // before use.
+ initializeJavaIDs(env);
+
return (MtpDevice*)env->GetLongField(javaDevice, field_context);
}
@@ -200,6 +295,8 @@
MtpDevice* device = MtpDevice::open(deviceNameStr, fd);
env->ReleaseStringUTFChars(deviceName, deviceNameStr);
+ // The jfieldID `field_context` needs to be initialized before use below.
+ initializeJavaIDs(env);
if (device)
env->SetLongField(thiz, field_context, (jlong)device);
return (jboolean)(device != NULL);
@@ -781,256 +878,7 @@
int register_android_mtp_MtpDevice(JNIEnv *env)
{
- jclass clazz;
-
ALOGD("register_android_mtp_MtpDevice\n");
-
- clazz = env->FindClass("android/mtp/MtpDeviceInfo");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpDeviceInfo");
- return -1;
- }
- constructor_deviceInfo = env->GetMethodID(clazz, "<init>", "()V");
- if (constructor_deviceInfo == NULL) {
- ALOGE("Can't find android/mtp/MtpDeviceInfo constructor");
- return -1;
- }
- field_deviceInfo_manufacturer = env->GetFieldID(clazz, "mManufacturer", "Ljava/lang/String;");
- if (field_deviceInfo_manufacturer == NULL) {
- ALOGE("Can't find MtpDeviceInfo.mManufacturer");
- return -1;
- }
- field_deviceInfo_model = env->GetFieldID(clazz, "mModel", "Ljava/lang/String;");
- if (field_deviceInfo_model == NULL) {
- ALOGE("Can't find MtpDeviceInfo.mModel");
- return -1;
- }
- field_deviceInfo_version = env->GetFieldID(clazz, "mVersion", "Ljava/lang/String;");
- if (field_deviceInfo_version == NULL) {
- ALOGE("Can't find MtpDeviceInfo.mVersion");
- return -1;
- }
- field_deviceInfo_serialNumber = env->GetFieldID(clazz, "mSerialNumber", "Ljava/lang/String;");
- if (field_deviceInfo_serialNumber == NULL) {
- ALOGE("Can't find MtpDeviceInfo.mSerialNumber");
- return -1;
- }
- field_deviceInfo_operationsSupported = env->GetFieldID(clazz, "mOperationsSupported", "[I");
- if (field_deviceInfo_operationsSupported == NULL) {
- ALOGE("Can't find MtpDeviceInfo.mOperationsSupported");
- return -1;
- }
- field_deviceInfo_eventsSupported = env->GetFieldID(clazz, "mEventsSupported", "[I");
- if (field_deviceInfo_eventsSupported == NULL) {
- ALOGE("Can't find MtpDeviceInfo.mEventsSupported");
- return -1;
- }
- clazz_deviceInfo = (jclass)env->NewGlobalRef(clazz);
-
- clazz = env->FindClass("android/mtp/MtpStorageInfo");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpStorageInfo");
- return -1;
- }
- constructor_storageInfo = env->GetMethodID(clazz, "<init>", "()V");
- if (constructor_storageInfo == NULL) {
- ALOGE("Can't find android/mtp/MtpStorageInfo constructor");
- return -1;
- }
- field_storageInfo_storageId = env->GetFieldID(clazz, "mStorageId", "I");
- if (field_storageInfo_storageId == NULL) {
- ALOGE("Can't find MtpStorageInfo.mStorageId");
- return -1;
- }
- field_storageInfo_maxCapacity = env->GetFieldID(clazz, "mMaxCapacity", "J");
- if (field_storageInfo_maxCapacity == NULL) {
- ALOGE("Can't find MtpStorageInfo.mMaxCapacity");
- return -1;
- }
- field_storageInfo_freeSpace = env->GetFieldID(clazz, "mFreeSpace", "J");
- if (field_storageInfo_freeSpace == NULL) {
- ALOGE("Can't find MtpStorageInfo.mFreeSpace");
- return -1;
- }
- field_storageInfo_description = env->GetFieldID(clazz, "mDescription", "Ljava/lang/String;");
- if (field_storageInfo_description == NULL) {
- ALOGE("Can't find MtpStorageInfo.mDescription");
- return -1;
- }
- field_storageInfo_volumeIdentifier = env->GetFieldID(clazz, "mVolumeIdentifier", "Ljava/lang/String;");
- if (field_storageInfo_volumeIdentifier == NULL) {
- ALOGE("Can't find MtpStorageInfo.mVolumeIdentifier");
- return -1;
- }
- clazz_storageInfo = (jclass)env->NewGlobalRef(clazz);
-
- clazz = env->FindClass("android/mtp/MtpObjectInfo");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpObjectInfo");
- return -1;
- }
- constructor_objectInfo = env->GetMethodID(clazz, "<init>", "()V");
- if (constructor_objectInfo == NULL) {
- ALOGE("Can't find android/mtp/MtpObjectInfo constructor");
- return -1;
- }
- field_objectInfo_handle = env->GetFieldID(clazz, "mHandle", "I");
- if (field_objectInfo_handle == NULL) {
- ALOGE("Can't find MtpObjectInfo.mHandle");
- return -1;
- }
- field_objectInfo_storageId = env->GetFieldID(clazz, "mStorageId", "I");
- if (field_objectInfo_storageId == NULL) {
- ALOGE("Can't find MtpObjectInfo.mStorageId");
- return -1;
- }
- field_objectInfo_format = env->GetFieldID(clazz, "mFormat", "I");
- if (field_objectInfo_format == NULL) {
- ALOGE("Can't find MtpObjectInfo.mFormat");
- return -1;
- }
- field_objectInfo_protectionStatus = env->GetFieldID(clazz, "mProtectionStatus", "I");
- if (field_objectInfo_protectionStatus == NULL) {
- ALOGE("Can't find MtpObjectInfo.mProtectionStatus");
- return -1;
- }
- field_objectInfo_compressedSize = env->GetFieldID(clazz, "mCompressedSize", "I");
- if (field_objectInfo_compressedSize == NULL) {
- ALOGE("Can't find MtpObjectInfo.mCompressedSize");
- return -1;
- }
- field_objectInfo_thumbFormat = env->GetFieldID(clazz, "mThumbFormat", "I");
- if (field_objectInfo_thumbFormat == NULL) {
- ALOGE("Can't find MtpObjectInfo.mThumbFormat");
- return -1;
- }
- field_objectInfo_thumbCompressedSize = env->GetFieldID(clazz, "mThumbCompressedSize", "I");
- if (field_objectInfo_thumbCompressedSize == NULL) {
- ALOGE("Can't find MtpObjectInfo.mThumbCompressedSize");
- return -1;
- }
- field_objectInfo_thumbPixWidth = env->GetFieldID(clazz, "mThumbPixWidth", "I");
- if (field_objectInfo_thumbPixWidth == NULL) {
- ALOGE("Can't find MtpObjectInfo.mThumbPixWidth");
- return -1;
- }
- field_objectInfo_thumbPixHeight = env->GetFieldID(clazz, "mThumbPixHeight", "I");
- if (field_objectInfo_thumbPixHeight == NULL) {
- ALOGE("Can't find MtpObjectInfo.mThumbPixHeight");
- return -1;
- }
- field_objectInfo_imagePixWidth = env->GetFieldID(clazz, "mImagePixWidth", "I");
- if (field_objectInfo_imagePixWidth == NULL) {
- ALOGE("Can't find MtpObjectInfo.mImagePixWidth");
- return -1;
- }
- field_objectInfo_imagePixHeight = env->GetFieldID(clazz, "mImagePixHeight", "I");
- if (field_objectInfo_imagePixHeight == NULL) {
- ALOGE("Can't find MtpObjectInfo.mImagePixHeight");
- return -1;
- }
- field_objectInfo_imagePixDepth = env->GetFieldID(clazz, "mImagePixDepth", "I");
- if (field_objectInfo_imagePixDepth == NULL) {
- ALOGE("Can't find MtpObjectInfo.mImagePixDepth");
- return -1;
- }
- field_objectInfo_parent = env->GetFieldID(clazz, "mParent", "I");
- if (field_objectInfo_parent == NULL) {
- ALOGE("Can't find MtpObjectInfo.mParent");
- return -1;
- }
- field_objectInfo_associationType = env->GetFieldID(clazz, "mAssociationType", "I");
- if (field_objectInfo_associationType == NULL) {
- ALOGE("Can't find MtpObjectInfo.mAssociationType");
- return -1;
- }
- field_objectInfo_associationDesc = env->GetFieldID(clazz, "mAssociationDesc", "I");
- if (field_objectInfo_associationDesc == NULL) {
- ALOGE("Can't find MtpObjectInfo.mAssociationDesc");
- return -1;
- }
- field_objectInfo_sequenceNumber = env->GetFieldID(clazz, "mSequenceNumber", "I");
- if (field_objectInfo_sequenceNumber == NULL) {
- ALOGE("Can't find MtpObjectInfo.mSequenceNumber");
- return -1;
- }
- field_objectInfo_name = env->GetFieldID(clazz, "mName", "Ljava/lang/String;");
- if (field_objectInfo_name == NULL) {
- ALOGE("Can't find MtpObjectInfo.mName");
- return -1;
- }
- field_objectInfo_dateCreated = env->GetFieldID(clazz, "mDateCreated", "J");
- if (field_objectInfo_dateCreated == NULL) {
- ALOGE("Can't find MtpObjectInfo.mDateCreated");
- return -1;
- }
- field_objectInfo_dateModified = env->GetFieldID(clazz, "mDateModified", "J");
- if (field_objectInfo_dateModified == NULL) {
- ALOGE("Can't find MtpObjectInfo.mDateModified");
- return -1;
- }
- field_objectInfo_keywords = env->GetFieldID(clazz, "mKeywords", "Ljava/lang/String;");
- if (field_objectInfo_keywords == NULL) {
- ALOGE("Can't find MtpObjectInfo.mKeywords");
- return -1;
- }
- clazz_objectInfo = (jclass)env->NewGlobalRef(clazz);
-
- clazz = env->FindClass("android/mtp/MtpEvent");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpEvent");
- return -1;
- }
- constructor_event = env->GetMethodID(clazz, "<init>", "()V");
- if (constructor_event == NULL) {
- ALOGE("Can't find android/mtp/MtpEvent constructor");
- return -1;
- }
- field_event_eventCode = env->GetFieldID(clazz, "mEventCode", "I");
- if (field_event_eventCode == NULL) {
- ALOGE("Can't find MtpObjectInfo.mEventCode");
- return -1;
- }
- field_event_parameter1 = env->GetFieldID(clazz, "mParameter1", "I");
- if (field_event_parameter1 == NULL) {
- ALOGE("Can't find MtpObjectInfo.mParameter1");
- return -1;
- }
- field_event_parameter2 = env->GetFieldID(clazz, "mParameter2", "I");
- if (field_event_parameter2 == NULL) {
- ALOGE("Can't find MtpObjectInfo.mParameter2");
- return -1;
- }
- field_event_parameter3 = env->GetFieldID(clazz, "mParameter3", "I");
- if (field_event_parameter3 == NULL) {
- ALOGE("Can't find MtpObjectInfo.mParameter3");
- return -1;
- }
- clazz_event = (jclass)env->NewGlobalRef(clazz);
-
- clazz = env->FindClass("android/mtp/MtpDevice");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpDevice");
- return -1;
- }
- field_context = env->GetFieldID(clazz, "mNativeContext", "J");
- if (field_context == NULL) {
- ALOGE("Can't find MtpDevice.mNativeContext");
- return -1;
- }
- clazz = env->FindClass("java/io/IOException");
- if (clazz == NULL) {
- ALOGE("Can't find java.io.IOException");
- return -1;
- }
- clazz_io_exception = (jclass)env->NewGlobalRef(clazz);
- clazz = env->FindClass("android/os/OperationCanceledException");
- if (clazz == NULL) {
- ALOGE("Can't find android.os.OperationCanceledException");
- return -1;
- }
- clazz_operation_canceled_exception = (jclass)env->NewGlobalRef(clazz);
-
return AndroidRuntime::registerNativeMethods(env,
"android/mtp/MtpDevice", gMethods, NELEM(gMethods));
}
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 8a1ae92..b4844f7 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -24,6 +24,7 @@
#include <fcntl.h>
#include <utils/threads.h>
+#include "core_jni_helpers.h"
#include "jni.h"
#include <nativehelper/JNIPlatformHelp.h>
#include "android_runtime/AndroidRuntime.h"
@@ -34,6 +35,8 @@
using namespace android;
+static Mutex sMutex;
+
// MtpServer fields
static jfieldID field_MtpServer_nativeContext;
@@ -44,7 +47,25 @@
static jfieldID field_MtpStorage_removable;
static jfieldID field_MtpStorage_maxFileSize;
-static Mutex sMutex;
+// Initializer for the jfieldIDs above. This method must be invoked before accessing MtpServer and
+// MtpStorage fields.
+static void initializeJavaIDs(JNIEnv* env) {
+ static std::once_flag sJniInitialized;
+
+ std::call_once(sJniInitialized, [](JNIEnv *env) {
+ const jclass storage_clazz = FindClassOrDie(env, "android/mtp/MtpStorage");
+ field_MtpStorage_storageId = GetFieldIDOrDie(env, storage_clazz, "mStorageId", "I");
+ field_MtpStorage_path =
+ GetFieldIDOrDie(env, storage_clazz, "mPath", "Ljava/lang/String;");
+ field_MtpStorage_description =
+ GetFieldIDOrDie(env, storage_clazz, "mDescription", "Ljava/lang/String;");
+ field_MtpStorage_removable = GetFieldIDOrDie(env, storage_clazz, "mRemovable", "Z");
+ field_MtpStorage_maxFileSize = GetFieldIDOrDie(env, storage_clazz, "mMaxFileSize", "J");
+
+ const jclass server_clazz = FindClassOrDie(env, "android/mtp/MtpServer");
+ field_MtpServer_nativeContext = GetFieldIDOrDie(env, server_clazz, "mNativeContext", "J");
+ }, env);
+}
// ----------------------------------------------------------------------------
@@ -52,6 +73,7 @@
extern IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
+ initializeJavaIDs(env);
return (MtpServer*)env->GetLongField(thiz, field_MtpServer_nativeContext);
}
@@ -60,6 +82,8 @@
jboolean usePtp, jstring deviceInfoManufacturer, jstring deviceInfoModel,
jstring deviceInfoDeviceVersion, jstring deviceInfoSerialNumber)
{
+ initializeJavaIDs(env);
+
const char *deviceInfoManufacturerStr = env->GetStringUTFChars(deviceInfoManufacturer, NULL);
const char *deviceInfoModelStr = env->GetStringUTFChars(deviceInfoModel, NULL);
const char *deviceInfoDeviceVersionStr = env->GetStringUTFChars(deviceInfoDeviceVersion, NULL);
@@ -224,50 +248,6 @@
int register_android_mtp_MtpServer(JNIEnv *env)
{
- jclass clazz;
-
- clazz = env->FindClass("android/mtp/MtpStorage");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpStorage");
- return -1;
- }
- field_MtpStorage_storageId = env->GetFieldID(clazz, "mStorageId", "I");
- if (field_MtpStorage_storageId == NULL) {
- ALOGE("Can't find MtpStorage.mStorageId");
- return -1;
- }
- field_MtpStorage_path = env->GetFieldID(clazz, "mPath", "Ljava/lang/String;");
- if (field_MtpStorage_path == NULL) {
- ALOGE("Can't find MtpStorage.mPath");
- return -1;
- }
- field_MtpStorage_description = env->GetFieldID(clazz, "mDescription", "Ljava/lang/String;");
- if (field_MtpStorage_description == NULL) {
- ALOGE("Can't find MtpStorage.mDescription");
- return -1;
- }
- field_MtpStorage_removable = env->GetFieldID(clazz, "mRemovable", "Z");
- if (field_MtpStorage_removable == NULL) {
- ALOGE("Can't find MtpStorage.mRemovable");
- return -1;
- }
- field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
- if (field_MtpStorage_maxFileSize == NULL) {
- ALOGE("Can't find MtpStorage.mMaxFileSize");
- return -1;
- }
-
- clazz = env->FindClass("android/mtp/MtpServer");
- if (clazz == NULL) {
- ALOGE("Can't find android/mtp/MtpServer");
- return -1;
- }
- field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
- if (field_MtpServer_nativeContext == NULL) {
- ALOGE("Can't find MtpServer.mNativeContext");
- return -1;
- }
-
return AndroidRuntime::registerNativeMethods(env,
"android/mtp/MtpServer", gMethods, NELEM(gMethods));
}
diff --git a/media/jni/soundpool/Android.bp b/media/jni/soundpool/Android.bp
index 7b498e0..b3406cd 100644
--- a/media/jni/soundpool/Android.bp
+++ b/media/jni/soundpool/Android.bp
@@ -45,26 +45,30 @@
"modernize-return-braced-init-list",
"modernize-shrink-to-fit",
"modernize-unary-static-assert",
- "modernize-use-auto", // debatable - auto can obscure type
+ // "modernize-use-auto", // found in StreamManager.h, debatable - auto can obscure type
"modernize-use-bool-literals",
"modernize-use-default-member-init",
"modernize-use-emplace",
"modernize-use-equals-default",
"modernize-use-equals-delete",
- "modernize-use-nodiscard",
+ // "modernize-use-nodiscard", // found in SteamManager.h
"modernize-use-noexcept",
"modernize-use-nullptr",
"modernize-use-override",
//"modernize-use-trailing-return-type", // not necessarily more readable
"modernize-use-transparent-functors",
"modernize-use-uncaught-exceptions",
- "modernize-use-using",
+ //"modernize-use-using", // found in SoundManager.h
"performance-*",
// Remove some pedantic stylistic requirements.
"-google-readability-casting", // C++ casts not always necessary and may be verbose
"-google-readability-todo", // do not require TODO(info)
"-google-build-using-namespace", // Reenable and fix later.
+
+ "-google-explicit-constructor", // found in StreamManager.h
+ "-misc-non-private-member-variables-in-classes", // found in SoundManager.h
+ "-performance-unnecessary-value-param", // found in StreamManager.h
]
cc_defaults {
@@ -96,8 +100,7 @@
tidy_checks: tidy_errors,
tidy_checks_as_errors: tidy_errors,
tidy_flags: [
- "-format-style='file'",
- "--header-filter='frameworks/base/media/jni/soundpool'",
+ "-format-style=file",
],
}
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
index f400a71..f54e266 100644
--- a/media/jni/tuner/FrontendClient.cpp
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -588,14 +588,15 @@
break;
}
case TunerFrontendStatus::codeRates: {
- int size = s.get<TunerFrontendStatus::codeRates>().size();
- status.codeRates().resize(size);
- for (int i = 0; i < size; i++) {
- auto aidlCodeRate = s.get<TunerFrontendStatus::codeRates>()[i];
- status.codeRates()[i] =
- static_cast<hardware::tv::tuner::V1_1::FrontendInnerFec>(aidlCodeRate);
+ vector<hardware::tv::tuner::V1_1::FrontendInnerFec> codeRates;
+ for (auto aidlCodeRate : s.get<TunerFrontendStatus::codeRates>()) {
+ codeRates.push_back(
+ static_cast<hardware::tv::tuner::V1_1::FrontendInnerFec>(aidlCodeRate));
}
- hidlStatus.push_back(status);
+ if (codeRates.size() > 0) {
+ status.codeRates(codeRates);
+ hidlStatus.push_back(status);
+ }
break;
}
case TunerFrontendStatus::bandwidth: {
diff --git a/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp b/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp
index 1a51218..fdca3fa 100644
--- a/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp
+++ b/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test_helper_app {
name: "UidImportanceHelperApp",
manifest: "HelperAppManifest.xml",
@@ -8,4 +17,3 @@
"general-tests",
],
}
-
diff --git a/native/android/tests/activitymanager/nativeTests/Android.bp b/native/android/tests/activitymanager/nativeTests/Android.bp
index d4b5015..528ac12 100644
--- a/native/android/tests/activitymanager/nativeTests/Android.bp
+++ b/native/android/tests/activitymanager/nativeTests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_test {
name: "ActivityManagerNativeTestCases",
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 91bad7b..f9795c6 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -41,13 +41,13 @@
android:supportsRtl="true">
<service
- android:name=".DeviceDiscoveryService"
+ android:name=".CompanionDeviceDiscoveryService"
android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
android:exported="true">
</service>
<activity
- android:name=".DeviceChooserActivity"
+ android:name=".CompanionDeviceActivity"
android:theme="@style/ChooserActivity"
android:permission="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
android:exported="true">
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
similarity index 62%
rename from packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
rename to packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index c30d4bf..28072ca 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -24,6 +24,7 @@
import static java.util.Objects.requireNonNull;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.companion.AssociationRequest;
@@ -31,41 +32,52 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.database.DataSetObserver;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
+import android.util.SparseArray;
+import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
-import android.widget.AdapterView;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
-import com.android.companiondevicemanager.DeviceDiscoveryService.DeviceFilterPair;
+import com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DeviceFilterPair;
import com.android.internal.util.Preconditions;
-public class DeviceChooserActivity extends Activity {
+public class CompanionDeviceActivity extends Activity {
private static final boolean DEBUG = false;
- private static final String LOG_TAG = "DeviceChooserActivity";
+ private static final String LOG_TAG = CompanionDeviceActivity.class.getSimpleName();
+
+ static CompanionDeviceActivity sInstance;
View mLoadingIndicator = null;
ListView mDeviceListView;
private View mPairButton;
private View mCancelButton;
+ DevicesAdapter mDevicesAdapter;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (DEBUG) Log.i(LOG_TAG, "Started with intent " + getIntent());
+ Log.i(LOG_TAG, "Starting UI for " + getService().mRequest);
if (getService().mDevicesFound.isEmpty()) {
Log.e(LOG_TAG, "About to show UI, but no devices to show");
}
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ sInstance = this;
String deviceProfile = getRequest().getDeviceProfile();
String profilePrivacyDisclaimer = emptyIfNull(getRequest()
@@ -96,17 +108,14 @@
profileName,
getCallingAppName()), 0));
mDeviceListView = findViewById(R.id.device_list);
- final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter;
- mDeviceListView.setAdapter(adapter);
- mDeviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int pos, long l) {
- getService().mSelectedDevice =
- (DeviceFilterPair) adapterView.getItemAtPosition(pos);
- adapter.notifyDataSetChanged();
- }
+ mDevicesAdapter = new DevicesAdapter();
+ mDeviceListView.setAdapter(mDevicesAdapter);
+ mDeviceListView.setOnItemClickListener((adapterView, view, pos, l) -> {
+ getService().mSelectedDevice =
+ (DeviceFilterPair) adapterView.getItemAtPosition(pos);
+ mDevicesAdapter.notifyDataSetChanged();
});
- adapter.registerDataSetObserver(new DataSetObserver() {
+ mDevicesAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
onSelectionUpdate();
@@ -133,6 +142,12 @@
mCancelButton.setOnClickListener(v -> cancel());
}
+ static void notifyDevicesChanged() {
+ if (sInstance != null && !sInstance.isFinishing()) {
+ sInstance.mDevicesAdapter.notifyDataSetChanged();
+ }
+ }
+
private AssociationRequest getRequest() {
return getService().mRequest;
}
@@ -156,6 +171,7 @@
}
private void cancel() {
+ Log.i(LOG_TAG, "cancel()");
getService().onCancel();
setResult(RESULT_CANCELED);
finish();
@@ -170,6 +186,14 @@
}
}
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (sInstance == this) {
+ sInstance = null;
+ }
+ }
+
private CharSequence getCallingAppName() {
try {
final PackageManager packageManager = getPackageManager();
@@ -217,15 +241,91 @@
}
}
- private DeviceDiscoveryService getService() {
- return DeviceDiscoveryService.sInstance;
+ private CompanionDeviceDiscoveryService getService() {
+ return CompanionDeviceDiscoveryService.sInstance;
}
- protected void onDeviceConfirmed(DeviceFilterPair selectedDevice) {
+ protected void onDeviceConfirmed(DeviceFilterPair selectedDevice) {
+ Log.i(LOG_TAG, "onDeviceConfirmed(selectedDevice = " + selectedDevice + ")");
getService().onDeviceSelected(
getCallingPackage(), getDeviceMacAddress(selectedDevice.device));
setResult(RESULT_OK,
new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice.device));
finish();
}
+
+ class DevicesAdapter extends BaseAdapter {
+ private final Drawable mBluetoothIcon = icon(android.R.drawable.stat_sys_data_bluetooth);
+ private final Drawable mWifiIcon = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
+
+ private SparseArray<Integer> mColors = new SparseArray();
+
+ private Drawable icon(int drawableRes) {
+ Drawable icon = getResources().getDrawable(drawableRes, null);
+ icon.setTint(Color.DKGRAY);
+ return icon;
+ }
+
+ @Override
+ public View getView(
+ int position,
+ @Nullable View convertView,
+ @NonNull ViewGroup parent) {
+ TextView view = convertView instanceof TextView
+ ? (TextView) convertView
+ : newView();
+ bind(view, getItem(position));
+ return view;
+ }
+
+ private void bind(TextView textView, DeviceFilterPair device) {
+ textView.setText(device.getDisplayName());
+ textView.setBackgroundColor(
+ device.equals(getService().mSelectedDevice)
+ ? getColor(android.R.attr.colorControlHighlight)
+ : Color.TRANSPARENT);
+ textView.setCompoundDrawablesWithIntrinsicBounds(
+ device.device instanceof android.net.wifi.ScanResult
+ ? mWifiIcon
+ : mBluetoothIcon,
+ null, null, null);
+ textView.getCompoundDrawables()[0].setTint(getColor(android.R.attr.colorForeground));
+ }
+
+ private TextView newView() {
+ final TextView textView = new TextView(CompanionDeviceActivity.this);
+ textView.setTextColor(getColor(android.R.attr.colorForeground));
+ final int padding = CompanionDeviceActivity.getPadding(getResources());
+ textView.setPadding(padding, padding, padding, padding);
+ textView.setCompoundDrawablePadding(padding);
+ return textView;
+ }
+
+ private int getColor(int colorAttr) {
+ if (mColors.contains(colorAttr)) {
+ return mColors.get(colorAttr);
+ }
+ TypedValue typedValue = new TypedValue();
+ TypedArray a = obtainStyledAttributes(typedValue.data, new int[] { colorAttr });
+ int result = a.getColor(0, 0);
+ a.recycle();
+ mColors.put(colorAttr, result);
+ return result;
+ }
+
+ @Override
+ public int getCount() {
+ return getService().mDevicesFound.size();
+ }
+
+ @Override
+ public DeviceFilterPair getItem(int position) {
+ return getService().mDevicesFound.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+ }
}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
similarity index 80%
rename from packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
rename to packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 67d4b41..e620dfb 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -50,9 +50,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
@@ -60,12 +57,6 @@
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
-import android.util.SparseArray;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.TextView;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.ArrayUtils;
@@ -76,14 +67,14 @@
import java.util.List;
import java.util.Objects;
-public class DeviceDiscoveryService extends Service {
+public class CompanionDeviceDiscoveryService extends Service {
private static final boolean DEBUG = false;
- private static final String LOG_TAG = "DeviceDiscoveryService";
+ private static final String LOG_TAG = CompanionDeviceDiscoveryService.class.getSimpleName();
private static final long SCAN_TIMEOUT = 20000;
- static DeviceDiscoveryService sInstance;
+ static CompanionDeviceDiscoveryService sInstance;
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
@@ -102,12 +93,12 @@
AssociationRequest mRequest;
List<DeviceFilterPair> mDevicesFound;
DeviceFilterPair mSelectedDevice;
- DevicesAdapter mDevicesAdapter;
IFindDeviceCallback mFindCallback;
AndroidFuture<Association> mServiceCallback;
boolean mIsScanning = false;
- @Nullable DeviceChooserActivity mActivity = null;
+ @Nullable
+ CompanionDeviceActivity mActivity = null;
private final ICompanionDeviceDiscoveryService mBinder =
new ICompanionDeviceDiscoveryService.Stub() {
@@ -125,7 +116,8 @@
mFindCallback = findCallback;
mServiceCallback = serviceCallback;
Handler.getMain().sendMessage(obtainMessage(
- DeviceDiscoveryService::startDiscovery, DeviceDiscoveryService.this, request));
+ CompanionDeviceDiscoveryService::startDiscovery,
+ CompanionDeviceDiscoveryService.this, request));
}
};
@@ -151,7 +143,6 @@
mWifiManager = getSystemService(WifiManager.class);
mDevicesFound = new ArrayList<>();
- mDevicesAdapter = new DevicesAdapter();
sInstance = this;
}
@@ -165,7 +156,8 @@
mWifiFilters = CollectionUtils.filter(mFilters, WifiDeviceFilter.class);
mBluetoothFilters = CollectionUtils.filter(mFilters, BluetoothDeviceFilter.class);
mBLEFilters = CollectionUtils.filter(mFilters, BluetoothLeDeviceFilter.class);
- mBLEScanFilters = CollectionUtils.map(mBLEFilters, BluetoothLeDeviceFilter::getScanFilter);
+ mBLEScanFilters
+ = CollectionUtils.map(mBLEFilters, BluetoothLeDeviceFilter::getScanFilter);
reset();
} else if (DEBUG) Log.i(LOG_TAG, "startDiscovery: duplicate request: " + request);
@@ -223,7 +215,7 @@
}
mIsScanning = true;
Handler.getMain().sendMessageDelayed(
- obtainMessage(DeviceDiscoveryService::stopScan, this),
+ obtainMessage(CompanionDeviceDiscoveryService::stopScan, this),
SCAN_TIMEOUT);
}
@@ -237,7 +229,7 @@
stopScan();
mDevicesFound.clear();
mSelectedDevice = null;
- mDevicesAdapter.notifyDataSetChanged();
+ CompanionDeviceActivity.notifyDevicesChanged();
}
@Override
@@ -252,7 +244,7 @@
if (!mIsScanning) return;
mIsScanning = false;
- DeviceChooserActivity activity = mActivity;
+ CompanionDeviceActivity activity = mActivity;
if (activity != null) {
if (activity.mDeviceListView != null) {
activity.mDeviceListView.removeFooterView(activity.mLoadingIndicator);
@@ -276,7 +268,7 @@
if (device == null) return;
Handler.getMain().sendMessage(obtainMessage(
- DeviceDiscoveryService::onDeviceFoundMainThread, this, device));
+ CompanionDeviceDiscoveryService::onDeviceFoundMainThread, this, device));
}
@MainThread
@@ -292,7 +284,7 @@
onReadyToShowUI();
}
mDevicesFound.add(device);
- mDevicesAdapter.notifyDataSetChanged();
+ CompanionDeviceActivity.notifyDevicesChanged();
}
//TODO also, on timeout -> call onFailure
@@ -300,7 +292,7 @@
try {
mFindCallback.onSuccess(PendingIntent.getActivity(
this, 0,
- new Intent(this, DeviceChooserActivity.class),
+ new Intent(this, CompanionDeviceActivity.class),
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_IMMUTABLE));
} catch (RemoteException e) {
@@ -311,13 +303,13 @@
private void onDeviceLost(@Nullable DeviceFilterPair device) {
Log.i(LOG_TAG, "Lost device " + device.getDisplayName());
Handler.getMain().sendMessage(obtainMessage(
- DeviceDiscoveryService::onDeviceLostMainThread, this, device));
+ CompanionDeviceDiscoveryService::onDeviceLostMainThread, this, device));
}
@MainThread
void onDeviceLostMainThread(@Nullable DeviceFilterPair device) {
mDevicesFound.remove(device);
- mDevicesAdapter.notifyDataSetChanged();
+ CompanionDeviceActivity.notifyDevicesChanged();
}
void onDeviceSelected(String callingPackage, String deviceAddress) {
@@ -331,81 +323,6 @@
mServiceCallback.cancel(true);
}
- class DevicesAdapter extends BaseAdapter {
- private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
- private Drawable WIFI_ICON = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
-
- private SparseArray<Integer> mColors = new SparseArray();
-
- private Drawable icon(int drawableRes) {
- Drawable icon = getResources().getDrawable(drawableRes, null);
- icon.setTint(Color.DKGRAY);
- return icon;
- }
-
- @Override
- public View getView(
- int position,
- @Nullable View convertView,
- @NonNull ViewGroup parent) {
- TextView view = convertView instanceof TextView
- ? (TextView) convertView
- : newView();
- bind(view, getItem(position));
- return view;
- }
-
- private void bind(TextView textView, DeviceFilterPair device) {
- textView.setText(device.getDisplayName());
- textView.setBackgroundColor(
- device.equals(mSelectedDevice)
- ? getColor(android.R.attr.colorControlHighlight)
- : Color.TRANSPARENT);
- textView.setCompoundDrawablesWithIntrinsicBounds(
- device.device instanceof android.net.wifi.ScanResult
- ? WIFI_ICON
- : BLUETOOTH_ICON,
- null, null, null);
- textView.getCompoundDrawables()[0].setTint(getColor(android.R.attr.colorForeground));
- }
-
- private TextView newView() {
- final TextView textView = new TextView(DeviceDiscoveryService.this);
- textView.setTextColor(getColor(android.R.attr.colorForeground));
- final int padding = DeviceChooserActivity.getPadding(getResources());
- textView.setPadding(padding, padding, padding, padding);
- textView.setCompoundDrawablePadding(padding);
- return textView;
- }
-
- private int getColor(int colorAttr) {
- if (mColors.contains(colorAttr)) {
- return mColors.get(colorAttr);
- }
- TypedValue typedValue = new TypedValue();
- TypedArray a = obtainStyledAttributes(typedValue.data, new int[] { colorAttr });
- int result = a.getColor(0, 0);
- a.recycle();
- mColors.put(colorAttr, result);
- return result;
- }
-
- @Override
- public int getCount() {
- return mDevicesFound.size();
- }
-
- @Override
- public DeviceFilterPair getItem(int position) {
- return mDevicesFound.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
- }
-
/**
* A pair of device and a filter that matched this device if any.
*
diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
index f4b46e9..eafda4d 100644
--- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
+++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
@@ -44,7 +44,7 @@
private final boolean mCaptive;
private final String mVenueFriendlyName;
private final int mVenueInfoUrlSource;
- private final int mTermsAndConditionsSource;
+ private final int mUserPortalUrlSource;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -65,7 +65,7 @@
private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl,
boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive,
- String venueFriendlyName, int venueInfoUrlSource, int termsAndConditionsSource) {
+ String venueFriendlyName, int venueInfoUrlSource, int userPortalUrlSource) {
mRefreshTimeMillis = refreshTimeMillis;
mUserPortalUrl = userPortalUrl;
mVenueInfoUrl = venueInfoUrl;
@@ -75,7 +75,7 @@
mCaptive = captive;
mVenueFriendlyName = venueFriendlyName;
mVenueInfoUrlSource = venueInfoUrlSource;
- mTermsAndConditionsSource = termsAndConditionsSource;
+ mUserPortalUrlSource = userPortalUrlSource;
}
private CaptivePortalData(Parcel p) {
@@ -100,7 +100,7 @@
dest.writeBoolean(mCaptive);
dest.writeString(mVenueFriendlyName);
dest.writeInt(mVenueInfoUrlSource);
- dest.writeInt(mTermsAndConditionsSource);
+ dest.writeInt(mUserPortalUrlSource);
}
/**
@@ -130,7 +130,7 @@
public Builder(@Nullable CaptivePortalData data) {
if (data == null) return;
setRefreshTime(data.mRefreshTimeMillis)
- .setUserPortalUrl(data.mUserPortalUrl, data.mTermsAndConditionsSource)
+ .setUserPortalUrl(data.mUserPortalUrl, data.mUserPortalUrlSource)
.setVenueInfoUrl(data.mVenueInfoUrl, data.mVenueInfoUrlSource)
.setSessionExtendable(data.mIsSessionExtendable)
.setBytesRemaining(data.mByteLimit)
@@ -314,7 +314,7 @@
* @return The source that the user portal URL was obtained from
*/
public @CaptivePortalDataSource int getUserPortalUrlSource() {
- return mTermsAndConditionsSource;
+ return mUserPortalUrlSource;
}
/**
@@ -342,7 +342,7 @@
public int hashCode() {
return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl,
mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName,
- mVenueInfoUrlSource, mTermsAndConditionsSource);
+ mVenueInfoUrlSource, mUserPortalUrlSource);
}
@Override
@@ -358,7 +358,7 @@
&& mCaptive == other.mCaptive
&& Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName)
&& mVenueInfoUrlSource == other.mVenueInfoUrlSource
- && mTermsAndConditionsSource == other.mTermsAndConditionsSource;
+ && mUserPortalUrlSource == other.mUserPortalUrlSource;
}
@Override
@@ -373,7 +373,7 @@
+ ", captive: " + mCaptive
+ ", venueFriendlyName: " + mVenueFriendlyName
+ ", venueInfoUrlSource: " + mVenueInfoUrlSource
- + ", termsAndConditionsSource: " + mTermsAndConditionsSource
+ + ", userPortalUrlSource: " + mUserPortalUrlSource
+ "}";
}
}
diff --git a/packages/Connectivity/framework/src/android/net/IpPrefix.java b/packages/Connectivity/framework/src/android/net/IpPrefix.java
index bcb65fa..d2ee7d1 100644
--- a/packages/Connectivity/framework/src/android/net/IpPrefix.java
+++ b/packages/Connectivity/framework/src/android/net/IpPrefix.java
@@ -24,6 +24,8 @@
import android.os.Parcelable;
import android.util.Pair;
+import com.android.net.module.util.NetUtils;
+
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -59,7 +61,7 @@
throw new IllegalArgumentException(
"IpPrefix has " + address.length + " bytes which is neither 4 nor 16");
}
- NetworkUtils.maskRawAddress(address, prefixLength);
+ NetUtils.maskRawAddress(address, prefixLength);
}
/**
@@ -190,7 +192,7 @@
if (addrBytes == null || addrBytes.length != this.address.length) {
return false;
}
- NetworkUtils.maskRawAddress(addrBytes, prefixLength);
+ NetUtils.maskRawAddress(addrBytes, prefixLength);
return Arrays.equals(this.address, addrBytes);
}
@@ -204,7 +206,7 @@
public boolean containsPrefix(@NonNull IpPrefix otherPrefix) {
if (otherPrefix.getPrefixLength() < prefixLength) return false;
final byte[] otherAddress = otherPrefix.getRawAddress();
- NetworkUtils.maskRawAddress(otherAddress, prefixLength);
+ NetUtils.maskRawAddress(otherAddress, prefixLength);
return Arrays.equals(otherAddress, address);
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
index 26d14cb..cd76f40 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -205,6 +205,7 @@
NET_CAPABILITY_OEM_PRIVATE,
NET_CAPABILITY_VEHICLE_INTERNAL,
NET_CAPABILITY_NOT_VCN_MANAGED,
+ NET_CAPABILITY_ENTERPRISE,
})
public @interface NetCapability { }
@@ -415,8 +416,17 @@
@SystemApi
public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
+ /**
+ * Indicates that this network is intended for enterprise use.
+ * <p>
+ * 5G URSP rules may indicate that all data should use a connection dedicated for enterprise
+ * use. If the enterprise capability is requested, all enterprise traffic will be routed over
+ * the connection with this capability.
+ */
+ public static final int NET_CAPABILITY_ENTERPRISE = 29;
+
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
- private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VCN_MANAGED;
+ private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_ENTERPRISE;
/**
* Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -474,7 +484,8 @@
| (1 << NET_CAPABILITY_MCX)
| (1 << NET_CAPABILITY_RCS)
| (1 << NET_CAPABILITY_VEHICLE_INTERNAL)
- | (1 << NET_CAPABILITY_XCAP);
+ | (1 << NET_CAPABILITY_XCAP)
+ | (1 << NET_CAPABILITY_ENTERPRISE);
/**
* Capabilities that force network to be restricted.
@@ -2028,8 +2039,9 @@
case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY";
case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED";
case NET_CAPABILITY_OEM_PRIVATE: return "OEM_PRIVATE";
- case NET_CAPABILITY_VEHICLE_INTERNAL: return "NET_CAPABILITY_VEHICLE_INTERNAL";
+ case NET_CAPABILITY_VEHICLE_INTERNAL: return "VEHICLE_INTERNAL";
case NET_CAPABILITY_NOT_VCN_MANAGED: return "NOT_VCN_MANAGED";
+ case NET_CAPABILITY_ENTERPRISE: return "ENTERPRISE";
default: return Integer.toString(capability);
}
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkUtils.java b/packages/Connectivity/framework/src/android/net/NetworkUtils.java
index 8be4af7..9ccb04a 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkUtils.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkUtils.java
@@ -29,7 +29,6 @@
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.SocketException;
-import java.net.UnknownHostException;
import java.util.Locale;
import java.util.TreeSet;
@@ -232,46 +231,6 @@
}
/**
- * Masks a raw IP address byte array with the specified prefix length.
- */
- public static void maskRawAddress(byte[] array, int prefixLength) {
- if (prefixLength < 0 || prefixLength > array.length * 8) {
- throw new RuntimeException("IP address with " + array.length +
- " bytes has invalid prefix length " + prefixLength);
- }
-
- int offset = prefixLength / 8;
- int remainder = prefixLength % 8;
- byte mask = (byte)(0xFF << (8 - remainder));
-
- if (offset < array.length) array[offset] = (byte)(array[offset] & mask);
-
- offset++;
-
- for (; offset < array.length; offset++) {
- array[offset] = 0;
- }
- }
-
- /**
- * Get InetAddress masked with prefixLength. Will never return null.
- * @param address the IP address to mask with
- * @param prefixLength the prefixLength used to mask the IP
- */
- public static InetAddress getNetworkPart(InetAddress address, int prefixLength) {
- byte[] array = address.getAddress();
- maskRawAddress(array, prefixLength);
-
- InetAddress netPart = null;
- try {
- netPart = InetAddress.getByAddress(array);
- } catch (UnknownHostException e) {
- throw new RuntimeException("getNetworkPart error - " + e.toString());
- }
- return netPart;
- }
-
- /**
* Returns the implicit netmask of an IPv4 address, as was the custom before 1993.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/packages/InputDevices/OWNERS b/packages/InputDevices/OWNERS
index 0313a40..f0d6db8 100644
--- a/packages/InputDevices/OWNERS
+++ b/packages/InputDevices/OWNERS
@@ -1,2 +1 @@
-michaelwr@google.com
-svv@google.com
+include /services/core/java/com/android/server/input/OWNERS
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
index 8b4db92..2946db3 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
@@ -27,9 +27,11 @@
private static final String SETTING = Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS;
private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag";
private static final String KEY_NON_INCREMENTAL_ONLY = "non_incremental_only";
+ private static final String KEY_IS_DEVICE_TRANSFER = "is_device_transfer";
private boolean mFakeEncryptionFlag;
private boolean mIsNonIncrementalOnly;
+ private boolean mIsDeviceTransfer;
public LocalTransportParameters(Handler handler, ContentResolver resolver) {
super(handler, resolver, Settings.Secure.getUriFor(SETTING));
@@ -43,6 +45,10 @@
return mIsNonIncrementalOnly;
}
+ boolean isDeviceTransfer() {
+ return mIsDeviceTransfer;
+ }
+
public String getSettingValue(ContentResolver resolver) {
return Settings.Secure.getString(resolver, SETTING);
}
@@ -50,5 +56,6 @@
public void update(KeyValueListParser parser) {
mFakeEncryptionFlag = parser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
mIsNonIncrementalOnly = parser.getBoolean(KEY_NON_INCREMENTAL_ONLY, false);
+ mIsDeviceTransfer = parser.getBoolean(KEY_IS_DEVICE_TRANSFER, false);
}
}
diff --git a/packages/SettingsLib/BannerMessagePreference/Android.bp b/packages/SettingsLib/BannerMessagePreference/Android.bp
index 095975a..82e837b 100644
--- a/packages/SettingsLib/BannerMessagePreference/Android.bp
+++ b/packages/SettingsLib/BannerMessagePreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "SettingsLibBannerMessagePreference",
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
index c23ff05..ed49bf4 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "SettingsLibCollapsingToolbarBaseActivity",
diff --git a/packages/SettingsLib/EmergencyNumber/Android.bp b/packages/SettingsLib/EmergencyNumber/Android.bp
index 3c41f78..25b4905 100644
--- a/packages/SettingsLib/EmergencyNumber/Android.bp
+++ b/packages/SettingsLib/EmergencyNumber/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "SettingsLibEmergencyNumber",
diff --git a/packages/SettingsLib/FooterPreference/Android.bp b/packages/SettingsLib/FooterPreference/Android.bp
index 1af967f..11f39e7 100644
--- a/packages/SettingsLib/FooterPreference/Android.bp
+++ b/packages/SettingsLib/FooterPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "SettingsLibFooterPreference",
diff --git a/packages/SettingsLib/MainSwitchPreference/Android.bp b/packages/SettingsLib/MainSwitchPreference/Android.bp
index 1dc18f5..1feec21 100644
--- a/packages/SettingsLib/MainSwitchPreference/Android.bp
+++ b/packages/SettingsLib/MainSwitchPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "SettingsLibMainSwitchPreference",
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
index 52779bc..85c01c5 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout/main_switch_bar.xml
@@ -19,6 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
+ android:background="?android:attr/colorBackground"
android:orientation="vertical">
<LinearLayout
diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
index 74b6578..1c9298e 100644
--- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
+++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchBar.java
@@ -17,6 +17,7 @@
package com.android.settingslib.widget;
import android.content.Context;
+import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -29,6 +30,7 @@
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
+import androidx.core.content.res.TypedArrayUtils;
import com.android.settingslib.RestrictedLockUtils;
@@ -88,6 +90,17 @@
});
setChecked(mSwitch.isChecked());
+
+ if (attrs != null) {
+ final TypedArray a = context.obtainStyledAttributes(attrs,
+ androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/,
+ 0 /*defStyleRes*/);
+ final CharSequence title = TypedArrayUtils.getText(a,
+ androidx.preference.R.styleable.Preference_title,
+ androidx.preference.R.styleable.Preference_android_title);
+ setTitle(title);
+ a.recycle();
+ }
}
@Override
@@ -126,7 +139,7 @@
/**
* Set the title text
*/
- public void setTitle(String text) {
+ public void setTitle(CharSequence text) {
if (mTextView != null) {
mTextView.setText(text);
}
diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
index 274bf8d..35afec3 100644
--- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
+++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.content.res.TypedArray;
-import android.text.TextUtils;
import android.util.AttributeSet;
import androidx.core.content.res.TypedArrayUtils;
@@ -40,7 +39,7 @@
private final List<OnMainSwitchChangeListener> mSwitchChangeListeners = new ArrayList<>();
private MainSwitchBar mMainSwitchBar;
- private String mTitle;
+ private CharSequence mTitle;
private RestrictedLockUtils.EnforcedAdmin mEnforcedAdmin;
@@ -81,24 +80,28 @@
setLayoutResource(R.layout.main_switch_layout);
if (attrs != null) {
- TypedArray a = context.obtainStyledAttributes(attrs,
+ final TypedArray a = context.obtainStyledAttributes(attrs,
androidx.preference.R.styleable.Preference, 0 /*defStyleAttr*/,
0 /*defStyleRes*/);
final CharSequence title = TypedArrayUtils.getText(a,
androidx.preference.R.styleable.Preference_title,
androidx.preference.R.styleable.Preference_android_title);
- if (!TextUtils.isEmpty(title)) {
- setTitle(title.toString());
- }
+ setTitle(title);
a.recycle();
}
}
- /**
- * Set the preference title text
- */
- public void setTitle(String text) {
- mTitle = text;
+ @Override
+ public void setChecked(boolean checked) {
+ super.setChecked(checked);
+ if (mMainSwitchBar != null) {
+ mMainSwitchBar.setChecked(checked);
+ }
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+ mTitle = title;
if (mMainSwitchBar != null) {
mMainSwitchBar.setTitle(mTitle);
}
diff --git a/packages/SettingsLib/TopIntroPreference/Android.bp b/packages/SettingsLib/TopIntroPreference/Android.bp
index 03becbd..9577281 100644
--- a/packages/SettingsLib/TopIntroPreference/Android.bp
+++ b/packages/SettingsLib/TopIntroPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "SettingsLibTopIntroPreference",
diff --git a/packages/SettingsLib/UsageProgressBarPreference/Android.bp b/packages/SettingsLib/UsageProgressBarPreference/Android.bp
index 3331550..ad6e7ab 100644
--- a/packages/SettingsLib/UsageProgressBarPreference/Android.bp
+++ b/packages/SettingsLib/UsageProgressBarPreference/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_library {
name: "SettingsLibUsageProgressBarPreference",
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 32419f4..1f3e0e9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -205,7 +205,6 @@
void dispatchDeviceListUpdate() {
final List<MediaDevice> mediaDevices = new ArrayList<>(mMediaDevices);
- Collections.sort(mediaDevices, COMPARATOR);
for (DeviceCallback callback : getCallbacks()) {
callback.onDeviceListUpdate(mediaDevices);
}
@@ -472,6 +471,7 @@
synchronized (mMediaDevicesLock) {
mMediaDevices.clear();
mMediaDevices.addAll(devices);
+ Collections.sort(devices, COMPARATOR);
// Add disconnected bluetooth devices only when phone output device is available.
for (MediaDevice device : devices) {
final int type = device.getDeviceType();
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
index 647fd2a..552fa11 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputConstants.java
@@ -39,8 +39,7 @@
/**
* A string extra specifying a media package name.
*/
- public static final String EXTRA_PACKAGE_NAME =
- "com.android.settings.panel.extra.PACKAGE_NAME";
+ public static final String EXTRA_PACKAGE_NAME = "package_name";
/**
* An intent action to launch media output dialog.
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 2594840..f67e039 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -125,6 +125,8 @@
<uses-permission android:name="android.permission.MANAGE_CREDENTIAL_MANAGEMENT_APP" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
<uses-permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS" />
+ <uses-permission android:name="android.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS" />
+ <uses-permission android:name="android.permission.CLEAR_FREEZE_PERIOD" />
<uses-permission android:name="android.permission.QUERY_USERS" />
<uses-permission android:name="android.permission.MODIFY_QUIET_MODE" />
<uses-permission android:name="android.permission.ACCESS_LOWPAN_STATE"/>
@@ -398,6 +400,7 @@
<!-- Permission required for CTS to test sensor privacy behavior -->
<uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
+ <uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
<!-- Permission needed for CTS test - CallLogTest -->
<uses-permission android:name="com.android.voicemail.permission.READ_VOICEMAIL" />
diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS
index 34901f5..6d738f8 100644
--- a/packages/Shell/OWNERS
+++ b/packages/Shell/OWNERS
@@ -9,3 +9,4 @@
toddke@google.com
cbrubaker@google.com
omakoto@google.com
+michaelwr@google.com
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index fbe58c5..044216e 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -87,6 +87,7 @@
<uses-permission android:name="android.permission.MASTER_CLEAR" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
+ <uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
<!-- ActivityManager -->
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
index 71cdaf5..7986809 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
@@ -24,7 +24,7 @@
<include
style="@style/BouncerSecurityContainer"
layout="@layout/keyguard_host_view"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
index c75ee51..04e645b 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
@@ -41,14 +41,13 @@
android:layout_gravity="center">
<com.android.keyguard.KeyguardSecurityViewFlipper
android:id="@+id/view_flipper"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingTop="@dimen/keyguard_security_view_top_margin"
android:paddingStart="@dimen/keyguard_security_view_lateral_margin"
android:paddingEnd="@dimen/keyguard_security_view_lateral_margin"
- android:layout_gravity="center"
android:gravity="center">
</com.android.keyguard.KeyguardSecurityViewFlipper>
</com.android.keyguard.KeyguardSecurityContainer>
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml b/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
deleted file mode 100644
index e09bf7e..0000000
--- a/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2021 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<resources>
- <bool name="can_use_one_handed_bouncer">true</bool>
-</resources>
diff --git a/packages/SystemUI/res-keyguard/values/config.xml b/packages/SystemUI/res-keyguard/values/config.xml
index 6176f7c..8d9d6ee 100644
--- a/packages/SystemUI/res-keyguard/values/config.xml
+++ b/packages/SystemUI/res-keyguard/values/config.xml
@@ -22,5 +22,4 @@
<!-- Allow the menu hard key to be disabled in LockScreen on some devices [DO NOT TRANSLATE] -->
<bool name="config_disableMenuKeyInLockScreen">false</bool>
- <bool name="can_use_one_handed_bouncer">false</bool>
</resources>
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
index 9f66581..96e0193 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_new_fullscreen.xml
@@ -36,8 +36,4 @@
</vector>
</item>
- <item>
- <ripple android:color="@color/GM2_grey_600"></ripple>
- </item>
-
</layer-list>
diff --git a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
index 659b020..368c8df 100644
--- a/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
+++ b/packages/SystemUI/res/drawable/ic_open_in_new_window.xml
@@ -50,28 +50,7 @@
android:strokeWidth="1"
android:pathData="M 12.5 13.92 L 15.59 17 L 17 15.59 L 13.91 12.5 L 16.5 12.5 L 16.5 10.5 L 10.5 10.5 L 10.5 16.5 L 12.5 16.5 Z" />
</group>
- <group
- android:translateX="22.000000"
- android:translateY="2.000000">
- <group
- android:translateX="3.000000"
- android:translateY="3.000000">
- <group
- android:translateX="-3.000000"
- android:translateY="-3.000000">
- <path
- android:fillColor="#80868B"
- android:fillType="evenOdd"
- android:strokeWidth="1"
- android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
- </group>
- </group>
- </group>
</vector>
</item>
- <item>
- <ripple android:color="@color/GM2_grey_600"></ripple>
- </item>
-
</layer-list>
diff --git a/packages/SystemUI/res/layout/media_output_dialog.xml b/packages/SystemUI/res/layout/media_output_dialog.xml
index 73beefc..d996cee 100644
--- a/packages/SystemUI/res/layout/media_output_dialog.xml
+++ b/packages/SystemUI/res/layout/media_output_dialog.xml
@@ -32,7 +32,8 @@
android:id="@+id/header_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingEnd="@dimen/media_output_dialog_header_icon_padding"/>
+ android:paddingEnd="@dimen/media_output_dialog_header_icon_padding"
+ android:importantForAccessibility="no"/>
<LinearLayout
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 571cbbc..1ce87c1 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -20,7 +20,6 @@
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
- android:minHeight="48dp"
android:paddingTop="12dp">
<LinearLayout
android:id="@+id/label_group"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 23f3425..4ca59f5 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -37,12 +37,6 @@
android:layout_height="match_parent"
android:layout_width="match_parent" />
- <ViewStub
- android:id="@+id/keyguard_user_switcher_stub"
- android:layout="@layout/keyguard_user_switcher"
- android:layout_height="match_parent"
- android:layout_width="match_parent" />
-
<include
layout="@layout/keyguard_status_view"
android:visibility="gone" />
@@ -109,5 +103,11 @@
layout="@layout/keyguard_bottom_area"
android:visibility="gone" />
+ <ViewStub
+ android:id="@+id/keyguard_user_switcher_stub"
+ android:layout="@layout/keyguard_user_switcher"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent" />
+
<include layout="@layout/status_bar_expanded_plugin_frame"/>
</com.android.systemui.statusbar.phone.NotificationPanelView>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 13c0110..0893c14 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -91,6 +91,9 @@
<!-- The number of columns in the QuickSettings -->
<integer name="quick_settings_num_columns">3</integer>
+ <!-- The number of columns in the Quick Settings customizer -->
+ <integer name="quick_settings_edit_num_columns">@integer/quick_settings_num_columns</integer>
+
<!-- The number of rows in the QuickSettings -->
<integer name="quick_settings_max_rows">3</integer>
@@ -421,6 +424,9 @@
vibrator is capable of subtle vibrations -->
<bool name="config_vibrateOnIconAnimation">false</bool>
+ <!-- Adjust the theme on fully custom and decorated custom view notifications -->
+ <bool name="config_adjustThemeOnNotificationCustomViews">false</bool>
+
<!-- If true, enable the advance anti-falsing classifier on the lockscreen. On some devices it
does not work well, particularly with noisy touchscreens. Note that disabling it may
increase the rate of unintentional unlocks. -->
@@ -574,4 +580,7 @@
<!-- Whether to use the split 2-column notification shade -->
<bool name="config_use_split_notification_shade">false</bool>
+
+ <!-- Determines whether the shell features all run on another thread. -->
+ <bool name="config_enableShellMainThread">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4bc5a30..89c849a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -651,7 +651,7 @@
</dimen>
<!-- The height of a notification header -->
- <dimen name="notification_header_height">53dp</dimen>
+ <dimen name="notification_header_height">@*android:dimen/notification_header_height</dimen>
<!-- The height of the gap between adjacent notification sections. -->
<dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen>
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index d4bb128..3e16cd4 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -42,4 +42,6 @@
<bool name="flag_lockscreen_animations">false</bool>
<bool name="flag_toast_style">false</bool>
+
+ <bool name="flag_navigation_bar_overlay">false</bool>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index d2698ee..b3a29a3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -190,7 +190,7 @@
}
@Override
- public void onActivityDismissingDockedStack() {
+ public void onActivityDismissingDockedTask() {
mHandler.sendEmptyMessage(ON_ACTIVITY_DISMISSING_DOCKED_STACK);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index f511ed1..5f6fd30 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -29,17 +29,12 @@
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.util.TypedValue;
-import android.view.Gravity;
import android.view.MotionEvent;
-import android.view.OrientationEventListener;
import android.view.VelocityTracker;
-import android.view.View;
import android.view.ViewConfiguration;
-import android.view.ViewPropertyAnimator;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsAnimationControlListener;
@@ -60,7 +55,6 @@
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import java.util.List;
@@ -105,12 +99,6 @@
private boolean mDisappearAnimRunning;
private SwipeListener mSwipeListener;
- private boolean mIsSecurityViewLeftAligned = true;
- private boolean mOneHandedMode = false;
- private SecurityMode mSecurityMode = SecurityMode.Invalid;
- private ViewPropertyAnimator mRunningOneHandedAnimator;
- private final OrientationEventListener mOrientationEventListener;
-
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
@@ -169,20 +157,16 @@
// Used to notify the container when something interesting happens.
public interface SecurityCallback {
boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
-
void userActivity();
-
void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
/**
- * @param strongAuth wheher the user has authenticated with strong authentication like
- * pattern, password or PIN but not by trust agents or fingerprint
+ * @param strongAuth wheher the user has authenticated with strong authentication like
+ * pattern, password or PIN but not by trust agents or fingerprint
* @param targetUserId a user that needs to be the foreground user at the finish completion.
*/
void finish(boolean strongAuth, int targetUserId);
-
void reset();
-
void onCancelClicked();
}
@@ -240,136 +224,12 @@
super(context, attrs, defStyle);
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
mViewConfiguration = ViewConfiguration.get(context);
-
- mOrientationEventListener = new OrientationEventListener(context) {
- @Override
- public void onOrientationChanged(int orientation) {
- updateLayoutForSecurityMode(mSecurityMode);
- }
- };
}
void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
- mSecurityMode = securityMode;
mSecurityViewFlipper.setWindowInsetsAnimationCallback(mWindowInsetsAnimationCallback);
updateBiometricRetry(securityMode, faceAuthEnabled);
- updateLayoutForSecurityMode(securityMode);
- mOrientationEventListener.enable();
- }
-
- void updateLayoutForSecurityMode(SecurityMode securityMode) {
- mSecurityMode = securityMode;
- mOneHandedMode = canUseOneHandedBouncer();
-
- if (mOneHandedMode) {
- mIsSecurityViewLeftAligned = isOneHandedKeyguardLeftAligned(mContext);
- }
-
- updateSecurityViewGravity();
- updateSecurityViewLocation(false);
- }
-
- /** Return whether the one-handed keyguard should be enabled. */
- private boolean canUseOneHandedBouncer() {
- // Is it enabled?
- if (!getResources().getBoolean(
- com.android.internal.R.bool.config_enableOneHandedKeyguard)) {
- return false;
- }
-
- if (!KeyguardSecurityModel.isSecurityViewOneHanded(mSecurityMode)) {
- return false;
- }
-
- return getResources().getBoolean(R.bool.can_use_one_handed_bouncer);
- }
-
- /** Read whether the one-handed keyguard should be on the left/right from settings. */
- private boolean isOneHandedKeyguardLeftAligned(Context context) {
- try {
- return Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.ONE_HANDED_KEYGUARD_SIDE)
- == Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
- } catch (Settings.SettingNotFoundException ex) {
- return true;
- }
- }
-
- private void updateSecurityViewGravity() {
- View securityView = findKeyguardSecurityView();
-
- if (securityView == null) {
- return;
- }
-
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) securityView.getLayoutParams();
-
- if (mOneHandedMode) {
- lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
- } else {
- lp.gravity = Gravity.CENTER_HORIZONTAL;
- }
-
- securityView.setLayoutParams(lp);
- }
-
- /**
- * Moves the inner security view to the correct location (in one handed mode) with animation.
- * This is triggered when the user taps on the side of the screen that is not currently occupied
- * by the security view .
- */
- private void updateSecurityViewLocation(boolean animate) {
- View securityView = findKeyguardSecurityView();
-
- if (securityView == null) {
- return;
- }
-
- if (!mOneHandedMode) {
- securityView.setTranslationX(0);
- return;
- }
-
- if (mRunningOneHandedAnimator != null) {
- mRunningOneHandedAnimator.cancel();
- mRunningOneHandedAnimator = null;
- }
-
- int targetTranslation = mIsSecurityViewLeftAligned ? 0 : (int) (getMeasuredWidth() / 2f);
-
- if (animate) {
- mRunningOneHandedAnimator = securityView.animate().translationX(targetTranslation);
- mRunningOneHandedAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mRunningOneHandedAnimator.setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mRunningOneHandedAnimator = null;
- }
- });
-
- mRunningOneHandedAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- mRunningOneHandedAnimator.start();
- } else {
- securityView.setTranslationX(targetTranslation);
- }
- }
-
- @Nullable
- private KeyguardSecurityViewFlipper findKeyguardSecurityView() {
- for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
-
- if (isKeyguardSecurityView(child)) {
- return (KeyguardSecurityViewFlipper) child;
- }
- }
-
- return null;
- }
-
- private boolean isKeyguardSecurityView(View view) {
- return view instanceof KeyguardSecurityViewFlipper;
}
public void onPause() {
@@ -378,7 +238,6 @@
mAlertDialog = null;
}
mSecurityViewFlipper.setWindowInsetsAnimationCallback(null);
- mOrientationEventListener.disable();
}
@Override
@@ -460,44 +319,19 @@
if (mSwipeListener != null) {
mSwipeListener.onSwipeUp();
}
- } else {
- if (!mIsDragging) {
- handleTap(event);
- }
}
}
return true;
}
- private void handleTap(MotionEvent event) {
- // If we're using a fullscreen security mode, skip
- if (!mOneHandedMode) {
- return;
- }
-
- // Did the tap hit the "other" side of the bouncer?
- if ((mIsSecurityViewLeftAligned && (event.getX() > getWidth() / 2f))
- || (!mIsSecurityViewLeftAligned && (event.getX() < getWidth() / 2f))) {
- mIsSecurityViewLeftAligned = !mIsSecurityViewLeftAligned;
-
- Settings.Global.putInt(
- mContext.getContentResolver(),
- Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
- mIsSecurityViewLeftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
- : Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
-
- updateSecurityViewLocation(true);
- }
- }
-
void setSwipeListener(SwipeListener swipeListener) {
mSwipeListener = swipeListener;
}
private void startSpringAnimation(float startVelocity) {
mSpringAnimation
- .setStartVelocity(startVelocity)
- .animateToFinalPosition(0);
+ .setStartVelocity(startVelocity)
+ .animateToFinalPosition(0);
}
public void startDisappearAnimation(SecurityMode securitySelection) {
@@ -607,17 +441,18 @@
return insets.inset(0, 0, 0, inset);
}
+
private void showDialog(String title, String message) {
if (mAlertDialog != null) {
mAlertDialog.dismiss();
}
mAlertDialog = new AlertDialog.Builder(mContext)
- .setTitle(title)
- .setMessage(message)
- .setCancelable(false)
- .setNeutralButton(R.string.ok, null)
- .create();
+ .setTitle(title)
+ .setMessage(message)
+ .setCancelable(false)
+ .setNeutralButton(R.string.ok, null)
+ .create();
if (!(mContext instanceof Activity)) {
mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
}
@@ -655,44 +490,6 @@
}
}
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int maxHeight = 0;
- int maxWidth = 0;
- int childState = 0;
-
- int halfWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
- MeasureSpec.getSize(widthMeasureSpec) / 2,
- MeasureSpec.getMode(widthMeasureSpec));
-
- for (int i = 0; i < getChildCount(); i++) {
- final View view = getChildAt(i);
- if (view.getVisibility() != GONE) {
- if (mOneHandedMode && isKeyguardSecurityView(view)) {
- measureChildWithMargins(view, halfWidthMeasureSpec, 0,
- heightMeasureSpec, 0);
- } else {
- measureChildWithMargins(view, widthMeasureSpec, 0,
- heightMeasureSpec, 0);
- }
- final LayoutParams lp = (LayoutParams) view.getLayoutParams();
- maxWidth = Math.max(maxWidth,
- view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
- maxHeight = Math.max(maxHeight,
- view.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
- childState = combineMeasuredStates(childState, view.getMeasuredState());
- }
- }
-
- // Check against our minimum height and width
- maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
- maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
-
- setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
- resolveSizeAndState(maxHeight, heightMeasureSpec,
- childState << MEASURED_HEIGHT_STATE_SHIFT));
- }
-
void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
String message = null;
switch (userType) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index fdab8db..1a8d420 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -404,7 +404,6 @@
if (newView != null) {
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
mSecurityViewFlipperController.show(newView);
- mView.updateLayoutForSecurityMode(securityMode);
}
mSecurityCallback.onSecurityModeChanged(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index 631c248..c77c867 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -92,13 +92,4 @@
throw new IllegalStateException("Unknown security quality:" + security);
}
}
-
- /**
- * Returns whether the given security view should be used in a "one handed" way. This can be
- * used to change how the security view is drawn (e.g. take up less of the screen, and align to
- * one side).
- */
- public static boolean isSecurityViewOneHanded(SecurityMode securityMode) {
- return securityMode == SecurityMode.Pattern || securityMode == SecurityMode.PIN;
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
index 8cb1bc4..5db3349 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java
@@ -69,7 +69,9 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (mAnimator != null) mAnimator.start();
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ if (mAnimator != null) mAnimator.start();
+ }
return super.onTouchEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index a4a781d..e6a9d4f 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -160,10 +160,9 @@
public boolean onTouchEvent(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
doHapticKeyClick();
+ if (mAnimator != null) mAnimator.start();
}
- if (mAnimator != null) mAnimator.start();
-
return super.onTouchEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 9686c91f..79f0688 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -16,8 +16,8 @@
package com.android.systemui.appops;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static android.media.AudioManager.ACTION_MICROPHONE_MUTE_CHANGED;
import android.Manifest;
@@ -137,8 +137,8 @@
mAudioManager = audioManager;
mSensorPrivacyController = sensorPrivacyController;
mMicMuted = audioManager.isMicrophoneMute()
- || mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE);
- mCameraDisabled = mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA);
+ || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
+ mCameraDisabled = mSensorPrivacyController.isSensorBlocked(CAMERA);
mLocationManager = context.getSystemService(LocationManager.class);
mPackageManager = context.getPackageManager();
dumpManager.registerDumpable(TAG, this);
@@ -159,8 +159,8 @@
mSensorPrivacyController.addCallback(this);
mMicMuted = mAudioManager.isMicrophoneMute()
- || mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE);
- mCameraDisabled = mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA);
+ || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
+ mCameraDisabled = mSensorPrivacyController.isSensorBlocked(CAMERA);
mBGHandler.post(() -> mAudioRecordingCallback.onRecordingConfigChanged(
mAudioManager.getActiveRecordingConfigurations()));
@@ -583,16 +583,16 @@
@Override
public void onReceive(Context context, Intent intent) {
mMicMuted = mAudioManager.isMicrophoneMute()
- || mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_MICROPHONE);
+ || mSensorPrivacyController.isSensorBlocked(MICROPHONE);
updateSensorDisabledStatus();
}
@Override
public void onSensorBlockedChanged(int sensor, boolean blocked) {
mBGHandler.post(() -> {
- if (sensor == INDIVIDUAL_SENSOR_CAMERA) {
+ if (sensor == CAMERA) {
mCameraDisabled = blocked;
- } else if (sensor == INDIVIDUAL_SENSOR_MICROPHONE) {
+ } else if (sensor == MICROPHONE) {
mMicMuted = mAudioManager.isMicrophoneMute() || blocked;
}
updateSensorDisabledStatus();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
index d4678f3..127128d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java
@@ -103,6 +103,11 @@
*/
public void updateIndication(@IndicationType int type, KeyguardIndication newIndication,
boolean showImmediately) {
+ if (type == INDICATION_TYPE_NOW_PLAYING
+ || type == INDICATION_TYPE_REVERSE_CHARGING) {
+ // temporarily don't show here, instead use AmbientContainer b/181049781
+ return;
+ }
final boolean hasPreviousIndication = mIndicationMessages.get(type) != null;
final boolean hasNewIndication = newIndication != null;
if (!hasNewIndication) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 27ea64f8..70b7b04 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -25,7 +25,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -54,7 +53,6 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -116,7 +114,7 @@
// Tracks config changes that will actually recreate the nav bar
private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
- | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS
+ | ActivityInfo.CONFIG_SCREEN_LAYOUT
| ActivityInfo.CONFIG_UI_MODE);
@Inject
@@ -171,6 +169,7 @@
configurationController.addCallback(this);
mConfigChanges.applyNewConfig(mContext.getResources());
mNavBarOverlayController = navBarOverlayController;
+ mNavigationModeController.addListener(this);
}
@Override
@@ -188,17 +187,18 @@
@Override
public void onNavigationModeChanged(int mode) {
- // Workaround for b/132825155, for secondary users, we currently don't receive configuration
- // changes on overlay package change since SystemUI runs for the system user. In this case,
- // trigger a new configuration change to ensure that the nav bar is updated in the same way.
- int userId = ActivityManagerWrapper.getInstance().getCurrentUserId();
- if (userId != UserHandle.USER_SYSTEM) {
- mHandler.post(() -> {
- for (int i = 0; i < mNavigationBars.size(); i++) {
- recreateNavigationBar(mNavigationBars.keyAt(i));
+ mHandler.post(() -> {
+ for (int i = 0; i < mNavigationBars.size(); i++) {
+ NavigationBar navBar = mNavigationBars.valueAt(i);
+ if (navBar == null) {
+ continue;
}
- });
- }
+ NavigationBarView view = (NavigationBarView) mNavigationBars.get(i).getView();
+ if (view != null) {
+ view.updateStates();
+ }
+ }
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
index c526c5d..62b9458 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarOverlayController.java
@@ -21,6 +21,7 @@
import android.view.View;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.statusbar.FeatureFlags;
import java.util.function.Consumer;
@@ -31,16 +32,22 @@
public class NavigationBarOverlayController {
protected final Context mContext;
+ protected final FeatureFlags mFeatureFlags;
@Inject
- public NavigationBarOverlayController(Context context) {
+ public NavigationBarOverlayController(Context context, FeatureFlags featureFlags) {
mContext = context;
+ mFeatureFlags = featureFlags;
}
public Context getContext() {
return mContext;
}
+ public boolean isNavigationBarOverlayEnabled() {
+ return mFeatureFlags.isNavigationBarOverlayEnabled();
+ }
+
/**
* Initialize the controller with visibility change callback and light/dark icon color.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
index b55fa4d..61e1d61 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 8e75bec..19e3278 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -171,6 +171,7 @@
private NotificationPanelViewController mPanelView;
private FloatingRotationButton mFloatingRotationButton;
private RotationButtonController mRotationButtonController;
+ private NavigationBarOverlayController mNavBarOverlayController;
/**
* Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -339,8 +340,11 @@
isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton,
mRotationButtonListener);
- Dependency.get(NavigationBarOverlayController.class).init(
- mNavbarOverlayVisibilityChangeCallback, mLightIconColor, mDarkIconColor);
+ mNavBarOverlayController = Dependency.get(NavigationBarOverlayController.class);
+ if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+ mNavBarOverlayController.init(
+ mNavbarOverlayVisibilityChangeCallback, mLightIconColor, mDarkIconColor);
+ }
mConfiguration = new Configuration();
mTmpLastConfiguration = new Configuration();
@@ -431,8 +435,9 @@
// 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);
+ if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+ mNavBarOverlayController.setButtonState(isTransient, /* force */ false);
+ }
}
void onBarTransition(int newMode) {
@@ -666,7 +671,9 @@
}
mImeVisible = visible;
mRotationButtonController.getRotationButton().setCanShowRotationButton(!mImeVisible);
- Dependency.get(NavigationBarOverlayController.class).setCanShow(!mImeVisible);
+ if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+ mNavBarOverlayController.setCanShow(!mImeVisible);
+ }
}
public void setDisabledFlags(int disabledFlags) {
@@ -999,10 +1006,9 @@
} else {
updateButtonLocation(getRotateSuggestionButton(), inScreenSpace);
}
- final NavigationBarOverlayController navBarButtonsController =
- Dependency.get(NavigationBarOverlayController.class);
- if (navBarButtonsController.isVisible()) {
- updateButtonLocation(navBarButtonsController.getCurrentView(), inScreenSpace);
+ if (mNavBarOverlayController.isNavigationBarOverlayEnabled()
+ && mNavBarOverlayController.isVisible()) {
+ updateButtonLocation(mNavBarOverlayController.getCurrentView(), inScreenSpace);
}
return mTmpRegion;
}
@@ -1230,7 +1236,9 @@
if (mRotationButtonController != null) {
mRotationButtonController.registerListeners();
}
- Dependency.get(NavigationBarOverlayController.class).registerListeners();
+ if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+ mNavBarOverlayController.registerListeners();
+ }
getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
updateNavButtonIcons();
@@ -1247,7 +1255,10 @@
if (mRotationButtonController != null) {
mRotationButtonController.unregisterListeners();
}
- Dependency.get(NavigationBarOverlayController.class).unregisterListeners();
+
+ if (mNavBarOverlayController.isNavigationBarOverlayEnabled()) {
+ mNavBarOverlayController.unregisterListeners();
+ }
mEdgeBackGestureHandler.onNavBarDetached();
getViewTreeObserver().removeOnComputeInternalInsetsListener(
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
index 65d4e23..870e3be 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
@@ -132,7 +132,7 @@
Settings.Secure.putString(mCurrentUserContext.getContentResolver(),
Secure.NAVIGATION_MODE, String.valueOf(mode)));
if (DEBUG) {
- Log.e(TAG, "updateCurrentInteractionMode: mode=" + mode);
+ Log.d(TAG, "updateCurrentInteractionMode: mode=" + mode);
dumpAssetPaths(mCurrentUserContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index c8edaec..fe76668 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -29,7 +29,6 @@
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.qs.tileimpl.QSTileBaseView;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -56,7 +55,8 @@
private final ArrayList<View> mAllViews = new ArrayList<>();
/**
* List of {@link View}s representing Quick Settings that are being animated from the quick QS
- * position to the normal QS panel.
+ * position to the normal QS panel. These views will only show once the animation is complete,
+ * to prevent overlapping of semi transparent views
*/
private final ArrayList<View> mQuickQsViews = new ArrayList<>();
private final QuickQSPanel mQuickQsPanel;
@@ -233,7 +233,6 @@
// Quick tiles.
QSTileView quickTileView = mQuickQSPanelController.getTileView(tile);
if (quickTileView == null) continue;
- View qqsBgCircle = ((QSTileBaseView) quickTileView).getBgCircle();
getRelativePosition(loc1, quickTileView.getIcon().getIconView(), view);
getRelativePosition(loc2, tileIcon, view);
@@ -255,11 +254,6 @@
translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
- if (mFeatureFlags.isQSLabelsEnabled()) {
- firstPageBuilder.addFloat(qqsBgCircle, "alpha", 1, 1, 0);
- mAllViews.add(qqsBgCircle);
- }
-
} else { // These tiles disappear when expanding
firstPageBuilder.addFloat(quickTileView, "alpha", 1, 0);
translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
@@ -271,7 +265,11 @@
translationX);
}
- mQuickQsViews.add(tileView.getIconWithBackground());
+ if (mFeatureFlags.isQSLabelsEnabled()) {
+ mQuickQsViews.add(tileView);
+ } else {
+ mQuickQsViews.add(tileView.getIconWithBackground());
+ }
mAllViews.add(tileView.getIcon());
mAllViews.add(quickTileView);
} else if (mFullRows && isIconInAnimatedRow(count)) {
@@ -362,7 +360,7 @@
if(view == parent || view == null) return;
// Ignore tile pages as they can have some offset we don't want to take into account in
// RTL.
- if (!(view instanceof PagedTileLayout.TilePage || view instanceof SideLabelTileLayout)) {
+ if (!isAPage(view)) {
loc1[0] += view.getLeft();
loc1[1] += view.getTop();
}
@@ -374,6 +372,16 @@
getRelativePositionInt(loc1, (View) view.getParent(), parent);
}
+ // Returns true if the view is a possible page in PagedTileLayout
+ private boolean isAPage(View view) {
+ if (view instanceof PagedTileLayout.TilePage) {
+ return true;
+ } else if (view instanceof SideLabelTileLayout) {
+ return !(view instanceof QuickQSPanel.QQSSideLabelTileLayout);
+ }
+ return false;
+ }
+
public void setPosition(float position) {
if (mNeedsAnimatorUpdate) {
updateAnimators();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 91ae571..0563307 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -112,7 +112,7 @@
private int mMediaTotalBottomMargin;
private int mFooterMarginStartHorizontal;
private Consumer<Boolean> mMediaVisibilityChangedListener;
- private boolean mSideLabels;
+ protected boolean mSideLabels;
public QSPanel(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -201,16 +201,20 @@
mFooterPageIndicator.setNumPages(((PagedTileLayout) mTileLayout).getNumPages());
}
- // Allow the UI to be as big as it want's to, we're in a scroll view
- int newHeight = 10000;
- int availableHeight = MeasureSpec.getSize(heightMeasureSpec);
- int excessHeight = newHeight - availableHeight;
- // Measure with EXACTLY. That way, The content will only use excess height and will
- // be measured last, after other views and padding is accounted for. This only
- // works because our Layouts in here remeasure themselves with the exact content
- // height.
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
- ((PagedTileLayout) mTileLayout).setExcessHeight(excessHeight);
+ // In landscape, mTileLayout's parent is not the panel but a view that contains the
+ // tile layout and the media controls.
+ if (((View) mTileLayout).getParent() == this) {
+ // Allow the UI to be as big as it want's to, we're in a scroll view
+ int newHeight = 10000;
+ int availableHeight = MeasureSpec.getSize(heightMeasureSpec);
+ int excessHeight = newHeight - availableHeight;
+ // Measure with EXACTLY. That way, The content will only use excess height and will
+ // be measured last, after other views and padding is accounted for. This only
+ // works because our Layouts in here remeasure themselves with the exact content
+ // height.
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY);
+ ((PagedTileLayout) mTileLayout).setExcessHeight(excessHeight);
+ }
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -758,7 +762,7 @@
// Let's use 3 columns to match the current layout
int columns;
if (mSideLabels) {
- columns = horizontal ? 1 : 2;
+ columns = horizontal ? 2 : 4;
} else {
columns = horizontal ? 3 : TileLayout.NO_MAX_COLUMNS;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index fcb35e2..d60801e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -18,7 +18,6 @@
import static com.android.systemui.media.dagger.MediaModule.QS_PANEL;
import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS;
-import static com.android.systemui.qs.dagger.QSFlagsModule.QS_LABELS_FLAG;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
import android.annotation.NonNull;
@@ -66,7 +65,6 @@
private BrightnessMirrorController mBrightnessMirrorController;
private boolean mGridContentVisible = true;
- private boolean mQsLabelsFlag;
private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
new QSPanel.OnConfigurationChangedListener() {
@@ -93,7 +91,6 @@
DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
BrightnessSlider.Factory brightnessSliderFactory,
- @Named(QS_LABELS_FLAG) boolean qsLabelsFlag,
FeatureFlags featureFlags) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager, featureFlags);
@@ -108,9 +105,6 @@
mView.setBrightnessView(mBrightnessSlider.getRootView());
mBrightnessController = brightnessControllerFactory.create(mBrightnessSlider);
-
- mQsLabelsFlag = qsLabelsFlag;
- mSideLabels = qsLabelsFlag;
}
@Override
@@ -329,7 +323,7 @@
@Override
public void onTuningChanged(String key, String newValue) {
if (QS_REMOVE_LABELS.equals(key)) {
- if (!mQsLabelsFlag) return;
+ if (!mQSLabelFlag) return;
boolean newShowLabels = newValue == null || "0".equals(newValue);
if (mShowLabels == newShowLabels) return;
mShowLabels = newShowLabels;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 9426e71..f1174fb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -75,7 +75,7 @@
private final QSHost.Callback mQSHostCallback = this::setTiles;
protected boolean mShowLabels = true;
- protected boolean mSideLabels;
+ protected boolean mQSLabelFlag;
private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
new QSPanel.OnConfigurationChangedListener() {
@@ -118,11 +118,12 @@
mQSLogger = qsLogger;
mDumpManager = dumpManager;
mFeatureFlags = featureFlags;
+ mQSLabelFlag = featureFlags.isQSLabelsEnabled();
}
@Override
protected void onInit() {
- mView.initialize(mSideLabels);
+ mView.initialize(mQSLabelFlag);
mQSLogger.logAllTilesChangeListening(mView.isListening(), mView.getDumpableTag(), "");
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index a29ac3b..9b66b59 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -69,12 +69,22 @@
@Override
public TileLayout createRegularTileLayout() {
- return new QuickQSPanel.HeaderTileLayout(mContext);
+ if (mSideLabels) {
+ return new QQSSideLabelTileLayout(mContext);
+ } else {
+ return new QuickQSPanel.HeaderTileLayout(mContext);
+ }
}
@Override
protected QSTileLayout createHorizontalTileLayout() {
- return new DoubleLineTileLayout(mContext);
+ if (mSideLabels) {
+ TileLayout t = createRegularTileLayout();
+ t.setMaxColumns(2);
+ return t;
+ } else {
+ return new DoubleLineTileLayout(mContext);
+ }
}
@Override
@@ -331,4 +341,38 @@
}
}
}
+
+ static class QQSSideLabelTileLayout extends SideLabelTileLayout {
+ QQSSideLabelTileLayout(Context context) {
+ super(context, null);
+ setClipChildren(false);
+ setClipToPadding(false);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT);
+ lp.gravity = Gravity.CENTER_HORIZONTAL;
+ setLayoutParams(lp);
+ setMaxColumns(4);
+ }
+
+ @Override
+ public boolean updateResources() {
+ boolean b = super.updateResources();
+ mMaxAllowedRows = 2;
+ return b;
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateResources();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Make sure to always use the correct number of rows. As it's determined by the
+ // columns, just use as many as needed.
+ updateMaxRows(10000, mRecords.size());
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 383e932..671f8f7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -17,7 +17,6 @@
package com.android.systemui.qs;
import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL;
-import static com.android.systemui.qs.dagger.QSFlagsModule.QS_LABELS_FLAG;
import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER;
import com.android.internal.logging.MetricsLogger;
@@ -42,8 +41,6 @@
@QSScope
public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> {
- private boolean mUseSideLabels;
-
private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
newConfig -> {
int newMaxTiles = getResources().getInteger(R.integer.quick_qs_panel_max_columns);
@@ -58,12 +55,10 @@
@Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer,
@Named(QUICK_QS_PANEL) MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
- DumpManager dumpManager, @Named(QS_LABELS_FLAG) boolean qsLabelsFlag,
- FeatureFlags featureFlags
+ DumpManager dumpManager, FeatureFlags featureFlags
) {
super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
uiEventLogger, qsLogger, dumpManager, featureFlags);
- mUseSideLabels = qsLabelsFlag;
}
@Override
@@ -104,19 +99,7 @@
break;
}
}
- if (mUseSideLabels) {
- List<QSTile> newTiles = new ArrayList<>();
- for (int i = 0; i < tiles.size(); i += 2) {
- newTiles.add(tiles.get(i));
- }
- for (int i = 1; i < tiles.size(); i += 2) {
- newTiles.add(tiles.get(i));
- }
- super.setTiles(newTiles, true);
-
- } else {
- super.setTiles(tiles, true);
- }
+ super.setTiles(tiles, !mQSLabelFlag);
}
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
index 74a7ac1..4de4a78 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
@@ -20,11 +20,13 @@
import android.util.AttributeSet
import com.android.systemui.R
-open class SideLabelTileLayout(context: Context, attrs: AttributeSet) : TileLayout(context, attrs) {
+open class SideLabelTileLayout(
+ context: Context,
+ attrs: AttributeSet?
+) : TileLayout(context, attrs) {
override fun updateResources(): Boolean {
return super.updateResources().also {
- mResourceColumns = 2
mMaxAllowedRows = 4
mCellMarginHorizontal = (mCellMarginHorizontal * 1.2).toInt()
mCellMarginVertical = mCellMarginHorizontal
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index d559e07..14cbf98 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -124,6 +124,7 @@
public boolean updateResources() {
final Resources res = mContext.getResources();
mResourceColumns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
+ updateColumns();
mMaxCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
mCellMarginVertical= res.getDimensionPixelSize(R.dimen.qs_tile_margin_vertical);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 048fdc3..7a91421 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -75,6 +75,8 @@
private static final int ACTION_ADD = 1;
private static final int ACTION_MOVE = 2;
+ private static final int NUM_COLUMNS_ID = R.integer.quick_settings_edit_num_columns;
+
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -87,6 +89,7 @@
private int mEditIndex;
private int mTileDividerIndex;
private int mFocusIndex;
+
private boolean mNeedsFocus;
private List<String> mCurrentSpecs;
private List<TileInfo> mOtherTiles;
@@ -109,7 +112,7 @@
mDecoration = new TileItemDecoration(context);
mMarginDecoration = new MarginTileDecoration();
mMinNumTiles = context.getResources().getInteger(R.integer.quick_settings_min_num_tiles);
- mNumColumns = context.getResources().getInteger(R.integer.quick_settings_num_columns);
+ mNumColumns = context.getResources().getInteger(NUM_COLUMNS_ID);
mAccessibilityDelegate = new TileAdapterDelegate();
}
@@ -129,7 +132,7 @@
* @return {@code true} if the number of columns changed, {@code false} otherwise
*/
public boolean updateNumColumns() {
- int numColumns = mContext.getResources().getInteger(R.integer.quick_settings_num_columns);
+ int numColumns = mContext.getResources().getInteger(NUM_COLUMNS_ID);
if (numColumns != mNumColumns) {
mNumColumns = numColumns;
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index a699e2e..424aafa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -105,24 +105,27 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ mLabel.setSingleLine(false);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- // Remeasure view if the primary label requires more then 2 lines or the secondary label
- // text will be cut off.
- if (mLabel.getLineCount() > mMaxLabelLines || !TextUtils.isEmpty(mSecondLine.getText())
- && mSecondLine.getLineHeight() > mSecondLine.getHeight()) {
- if (!mLabel.isSingleLine()) {
- mLabel.setSingleLine();
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- } else {
- if (mLabel.isSingleLine()) {
- mLabel.setSingleLine(false);
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
+ // Remeasure view if the primary label requires more than mMaxLabelLines lines or the
+ // secondary label text will be cut off.
+ if (shouldLabelBeSingleLine()) {
+ mLabel.setSingleLine();
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
+ private boolean shouldLabelBeSingleLine() {
+ if (mLabel.getLineCount() > mMaxLabelLines) {
+ return true;
+ } else if (!TextUtils.isEmpty(mSecondLine.getText())
+ && mLabel.getLineCount() > mMaxLabelLines - 1) {
+ return true;
+ }
+ return false;
+ }
+
@Override
protected void handleStateChanged(QSTile.State state) {
super.handleStateChanged(state);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt
index dc81b702..c98de8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewHorizontal.kt
@@ -24,8 +24,8 @@
import android.graphics.drawable.RippleDrawable
import android.service.quicksettings.Tile.STATE_ACTIVE
import android.view.Gravity
-import android.view.View
import android.widget.LinearLayout
+import android.widget.RelativeLayout
import com.android.systemui.R
import com.android.systemui.plugins.qs.QSIconView
import com.android.systemui.plugins.qs.QSTile
@@ -37,7 +37,6 @@
) : QSTileView(context, icon, false) {
private var paintDrawable: PaintDrawable? = null
- private var divider: View? = null
init {
orientation = HORIZONTAL
@@ -49,7 +48,12 @@
override fun createLabel() {
super.createLabel()
- findViewById<LinearLayout>(R.id.label_group)?.gravity = Gravity.START
+ findViewById<LinearLayout>(R.id.label_group)?.apply {
+ gravity = Gravity.START
+ (layoutParams as? RelativeLayout.LayoutParams)?.apply {
+ removeRule(RelativeLayout.ALIGN_PARENT_TOP)
+ }
+ }
mLabel.gravity = Gravity.START
mLabel.textDirection = TEXT_DIRECTION_LOCALE
mSecondLine.gravity = Gravity.START
@@ -57,7 +61,7 @@
val padding = context.resources.getDimensionPixelSize(R.dimen.qs_tile_side_label_padding)
mLabelContainer.setPaddingRelative(0, padding, padding, padding)
(mLabelContainer.layoutParams as LayoutParams).gravity =
- Gravity.CENTER_VERTICAL or Gravity.START
+ Gravity.CENTER_VERTICAL or Gravity.START
}
override fun updateRippleSize() {
@@ -93,7 +97,6 @@
paintDrawable?.setTint(getCircleColor(state.state))
mSecondLine.setTextColor(mLabel.textColors)
mLabelContainer.background = null
- divider?.backgroundTintList = mLabel.textColors
}
override fun handleExpand(dualTarget: Boolean) {}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
index 3841dac..70287cd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
@@ -16,10 +16,13 @@
package com.android.systemui.qs.tiles;
-import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
+import static android.content.pm.PackageManager.FEATURE_CAMERA_TOGGLE;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.os.Handler;
import android.os.Looper;
import android.provider.DeviceConfig;
@@ -58,8 +61,8 @@
@Override
public boolean isAvailable() {
- return /*getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
- && */whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ return getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
+ && whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
"camera_toggle_enabled",
false));
}
@@ -75,7 +78,7 @@
}
@Override
- public int getSensorId() {
+ public @Sensor int getSensorId() {
return CAMERA;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
index 2f0071a..e9b712d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
@@ -16,10 +16,13 @@
package com.android.systemui.qs.tiles;
-import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
+import static android.content.pm.PackageManager.FEATURE_MICROPHONE_TOGGLE;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import android.hardware.SensorPrivacyManager;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.os.Handler;
import android.os.Looper;
import android.provider.DeviceConfig;
@@ -58,7 +61,9 @@
@Override
public boolean isAvailable() {
- return whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+ return getHost().getContext().getPackageManager()
+ .hasSystemFeature(FEATURE_MICROPHONE_TOGGLE)
+ && whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
"mic_toggle_enabled",
false));
}
@@ -74,7 +79,7 @@
}
@Override
- public int getSensorId() {
+ public @Sensor 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
index 00703e7..0c582bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java
@@ -17,7 +17,7 @@
package com.android.systemui.qs.tiles;
import android.content.Intent;
-import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.os.Handler;
import android.os.Looper;
import android.service.quicksettings.Tile;
@@ -49,7 +49,7 @@
/**
* @return Id of the sensor that will be toggled
*/
- public abstract @IndividualSensor int getSensorId();
+ public abstract @Sensor int getSensorId();
/**
* @return icon for the QS tile
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index a6433ae..89efda9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -46,6 +46,7 @@
private final UiEventLogger mUiEventLogger;
private final ScrollCaptureController mScrollCaptureController;
+ private final ScrollCaptureClient.Connection mConnection;
private ImageView mPreview;
private View mSave;
@@ -69,8 +70,10 @@
Context context) {
mUiEventLogger = uiEventLogger;
- mScrollCaptureController = new ScrollCaptureController(context,
- ScreenshotController.sScrollConnection, mainExecutor, bgExecutor, imageExporter);
+ mScrollCaptureController = new ScrollCaptureController(context, mainExecutor, bgExecutor,
+ imageExporter);
+
+ mConnection = ScreenshotController.takeScrollCaptureConnection();
}
@Override
@@ -98,15 +101,20 @@
public void onStart() {
super.onStart();
if (mPreview.getDrawable() == null) {
+ if (mConnection == null) {
+ Log.e(TAG, "Failed to get scroll capture connection, bailing out");
+ finishAndRemoveTask();
+ return;
+ }
doCapture();
}
}
- private void disableButtons() {
- mSave.setEnabled(false);
- mCancel.setEnabled(false);
- mEdit.setEnabled(false);
- mShare.setEnabled(false);
+ private void setButtonsEnabled(boolean enabled) {
+ mSave.setEnabled(enabled);
+ mCancel.setEnabled(enabled);
+ mEdit.setEnabled(enabled);
+ mShare.setEnabled(enabled);
}
private void doEdit(Uri uri) {
@@ -115,8 +123,7 @@
if (!TextUtils.isEmpty(editorPackage)) {
intent.setComponent(ComponentName.unflattenFromString(editorPackage));
}
- intent.setType("image/png");
- intent.setData(uri);
+ intent.setDataAndType(uri, "image/png");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
@@ -127,12 +134,11 @@
private void doShare(Uri uri) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
- intent.setData(uri);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent sharingChooserIntent = Intent.createChooser(intent, null)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
}
@@ -140,7 +146,7 @@
private void onClicked(View v) {
int id = v.getId();
v.setPressed(true);
- disableButtons();
+ setButtonsEnabled(false);
if (id == R.id.save) {
startExport(PendingAction.SAVE);
} else if (id == R.id.cancel) {
@@ -160,10 +166,12 @@
@Override
public void onError() {
Log.e(TAG, "Error exporting image data.");
+ setButtonsEnabled(true);
}
@Override
public void onExportComplete(Uri outputUri) {
+ setButtonsEnabled(true);
switch (action) {
case EDIT:
doEdit(outputUri);
@@ -181,7 +189,8 @@
}
private void doCapture() {
- mScrollCaptureController.start(new ScrollCaptureController.ScrollCaptureCallback() {
+ mScrollCaptureController.start(mConnection,
+ new ScrollCaptureController.ScrollCaptureCallback() {
@Override
public void onError() {
Log.e(TAG, "Error!");
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 31c693b..131fde6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -101,7 +101,7 @@
public class ScreenshotController {
private static final String TAG = logTag(ScreenshotController.class);
- public static ScrollCaptureClient.Connection sScrollConnection;
+ private static ScrollCaptureClient.Connection sScrollConnection;
/**
* POD used in the AsyncTask which saves an image in the background.
@@ -222,6 +222,12 @@
| ActivityInfo.CONFIG_SCREEN_LAYOUT
| ActivityInfo.CONFIG_ASSETS_PATHS);
+ public static @Nullable ScrollCaptureClient.Connection takeScrollCaptureConnection() {
+ ScrollCaptureClient.Connection connection = sScrollConnection;
+ sScrollConnection = null;
+ return connection;
+ }
+
@Inject
ScreenshotController(
Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
index 863116a..4a3ffa45 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
@@ -53,7 +53,6 @@
public static final int MAX_HEIGHT = 12000;
- private final Connection mConnection;
private final Context mContext;
private final Executor mUiExecutor;
@@ -65,10 +64,9 @@
private UUID mRequestId;
private ScrollCaptureCallback mCaptureCallback;
- public ScrollCaptureController(Context context, Connection connection, Executor uiExecutor,
- Executor bgExecutor, ImageExporter exporter) {
+ public ScrollCaptureController(Context context, Executor uiExecutor, Executor bgExecutor,
+ ImageExporter exporter) {
mContext = context;
- mConnection = connection;
mUiExecutor = uiExecutor;
mBgExecutor = bgExecutor;
mImageExporter = exporter;
@@ -78,16 +76,17 @@
/**
* Run scroll capture!
*
+ * @param connection connection to the remote window to be used
* @param callback request callback to report back to the service
*/
- public void start(ScrollCaptureCallback callback) {
+ public void start(Connection connection, ScrollCaptureCallback callback) {
mCaptureTime = ZonedDateTime.now();
mRequestId = UUID.randomUUID();
mCaptureCallback = callback;
float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),
SETTING_KEY_MAX_PAGES, MAX_PAGES_DEFAULT);
- mConnection.start(this::startCapture, maxPages);
+ connection.start(this::startCapture, maxPages);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
index 9f182e1..6586137 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
@@ -25,8 +25,8 @@
import android.content.res.Resources
import android.hardware.SensorPrivacyManager
import android.hardware.SensorPrivacyManager.EXTRA_SENSOR
-import android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA
-import android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE
+import android.hardware.SensorPrivacyManager.Sensors.CAMERA
+import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
import android.os.Bundle
import android.os.Handler
import android.text.Html
@@ -81,7 +81,7 @@
dismiss()
}
}
- if (!sensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor)) {
+ if (!sensorPrivacyManager.isSensorPrivacyEnabled(sensor)) {
finish()
return
}
@@ -89,9 +89,9 @@
mAlertParams.apply {
try {
mMessage = Html.fromHtml(getString(when (sensor) {
- INDIVIDUAL_SENSOR_MICROPHONE ->
+ MICROPHONE ->
R.string.sensor_privacy_start_use_mic_dialog_content
- INDIVIDUAL_SENSOR_CAMERA ->
+ CAMERA ->
R.string.sensor_privacy_start_use_camera_dialog_content
else -> Resources.ID_NULL
}, packageManager.getApplicationInfo(sensorUsePackageName, 0)
@@ -102,9 +102,9 @@
}
mIconId = when (sensor) {
- INDIVIDUAL_SENSOR_MICROPHONE ->
+ MICROPHONE ->
com.android.internal.R.drawable.perm_group_microphone
- INDIVIDUAL_SENSOR_CAMERA -> com.android.internal.R.drawable.perm_group_camera
+ CAMERA -> com.android.internal.R.drawable.perm_group_camera
else -> Resources.ID_NULL
}
@@ -121,7 +121,7 @@
override fun onStart() {
super.onStart()
- sensorPrivacyManager.suppressIndividualSensorPrivacyReminders(sensorUsePackageName, true)
+ sensorPrivacyManager.suppressSensorPrivacyReminders(sensorUsePackageName, true)
unsuppressImmediately = false
}
@@ -156,11 +156,11 @@
if (unsuppressImmediately) {
sensorPrivacyManager
- .suppressIndividualSensorPrivacyReminders(sensorUsePackageName, false)
+ .suppressSensorPrivacyReminders(sensorUsePackageName, false)
} else {
Handler(mainLooper).postDelayed({
sensorPrivacyManager
- .suppressIndividualSensorPrivacyReminders(sensorUsePackageName, false)
+ .suppressSensorPrivacyReminders(sensorUsePackageName, false)
}, SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS)
}
}
@@ -170,7 +170,7 @@
}
private fun disableSensorPrivacy() {
- sensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, false)
+ sensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, false)
unsuppressImmediately = true
setResult(RESULT_OK)
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 0bfc8e5..fea521f 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -72,8 +72,6 @@
private static final Uri BRIGHTNESS_FOR_VR_FLOAT_URI =
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT);
- private final float mMinimumBacklight;
- private final float mMaximumBacklight;
private final float mDefaultBacklight;
private final float mMinimumBacklightForVr;
private final float mMaximumBacklightForVr;
@@ -314,10 +312,6 @@
mDisplayId = mContext.getDisplayId();
PowerManager pm = context.getSystemService(PowerManager.class);
- mMinimumBacklight = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
- mMaximumBacklight = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
mDefaultBacklight = mContext.getDisplay().getBrightnessDefault();
mMinimumBacklightForVr = pm.getBrightnessConstraint(
PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR);
@@ -375,8 +369,8 @@
metric = mAutomatic
? MetricsEvent.ACTION_BRIGHTNESS_AUTO
: MetricsEvent.ACTION_BRIGHTNESS;
- minBacklight = mMinimumBacklight;
- maxBacklight = mMaximumBacklight;
+ minBacklight = PowerManager.BRIGHTNESS_MIN;
+ maxBacklight = PowerManager.BRIGHTNESS_MAX;
settingToChange = Settings.System.SCREEN_BRIGHTNESS_FLOAT;
}
final float valFloat = MathUtils.min(convertGammaToLinearFloat(value,
@@ -439,8 +433,8 @@
min = mMinimumBacklightForVr;
max = mMaximumBacklightForVr;
} else {
- min = mMinimumBacklight;
- max = mMaximumBacklight;
+ min = PowerManager.BRIGHTNESS_MIN;
+ max = PowerManager.BRIGHTNESS_MAX;
}
// convertGammaToLinearFloat returns 0-1
if (BrightnessSynchronizer.floatEquals(brightnessValue,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index 862c279..cf77e29 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -82,4 +82,8 @@
public boolean isMonetEnabled() {
return mFlagReader.isEnabled(R.bool.flag_monet);
}
+
+ public boolean isNavigationBarOverlayEnabled() {
+ return mFlagReader.isEnabled(R.bool.flag_navigation_bar_overlay);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
index f2adaf0..9ed9659 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java
@@ -207,7 +207,7 @@
sb.append(g.toJson());
count++;
}
- mLastSaveLen = count;
+ mLastSaveLen += count;
sb.append("]");
return sb.toString();
}
@@ -249,7 +249,9 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
save();
if (mLastSaveLen >= 0) {
- pw.println(String.valueOf(mLastSaveLen) + " gestures written to " + mLogfile);
+ pw.println(String.valueOf(mLastSaveLen)
+ + " gestures since last dump written to " + mLogfile);
+ mLastSaveLen = 0;
} else {
pw.println("error writing gestures");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 7c3b791..c8c0755 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -548,8 +548,6 @@
try {
mStatusBarService.onNotificationClear(
notification.getPackageName(),
- notification.getTag(),
- notification.getId(),
notification.getUser().getIdentifier(),
notification.getKey(),
dismissedByUserStats.dismissalSurface,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index d617dff..6b96ee4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -254,8 +254,6 @@
try {
mStatusBarService.onNotificationClear(
entry.getSbn().getPackageName(),
- entry.getSbn().getTag(),
- entry.getSbn().getId(),
entry.getSbn().getUser().getIdentifier(),
entry.getSbn().getKey(),
stats.dismissalSurface,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 5fff8c8..0ef4c4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -36,12 +36,12 @@
import android.view.ViewGroup;
import android.widget.TextView;
-import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ContrastColorUtil;
import com.android.internal.widget.CachingIconView;
import com.android.settingslib.Utils;
+import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.TransformState;
@@ -61,6 +61,7 @@
private int mLightTextColor;
private int mDarkTextColor;
private int mDefaultTextColor;
+ private boolean mAdjustTheme;
public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) {
@@ -97,6 +98,8 @@
mView = view;
mRow = row;
onReinflated();
+ mAdjustTheme = ctx.getResources().getBoolean(
+ R.bool.config_adjustThemeOnNotificationCustomViews);
}
/**
@@ -124,12 +127,12 @@
mLightTextColor = mView.getContext().getColor(
com.android.internal.R.color.notification_primary_text_color_light);
mDarkTextColor = mView.getContext().getColor(
- R.color.notification_primary_text_color_dark);
+ com.android.internal.R.color.notification_primary_text_color_dark);
Context themedContext = new ContextThemeWrapper(mView.getContext(),
- R.style.Theme_DeviceDefault_DayNight);
- mDefaultTextColor = Utils.getColorAttr(themedContext, R.attr.textColorPrimary)
- .getDefaultColor();
+ com.android.internal.R.style.Theme_DeviceDefault_DayNight);
+ mDefaultTextColor = Utils.getColorAttr(themedContext,
+ com.android.internal.R.attr.textColorPrimary).getDefaultColor();
}
protected boolean needsInversion(int defaultBackgroundColor, View view) {
@@ -208,7 +211,7 @@
}
protected void ensureThemeOnChildren() {
- if (mView == null) {
+ if (!mAdjustTheme || mView == null) {
return;
}
@@ -219,26 +222,20 @@
}
// Now let's check if there's unprotected text somewhere, and apply the theme if we find it.
- if (!(mView instanceof ViewGroup)) {
- return;
- }
- processChildrenTextColor((ViewGroup) mView);
+ processTextColorRecursive(mView);
}
- private void processChildrenTextColor(ViewGroup viewGroup) {
- if (viewGroup == null) {
- return;
- }
-
- for (int i = 0; i < viewGroup.getChildCount(); i++) {
- View child = viewGroup.getChildAt(i);
- if (child instanceof TextView) {
- int foreground = ((TextView) child).getCurrentTextColor();
- if (foreground == mLightTextColor || foreground == mDarkTextColor) {
- ((TextView) child).setTextColor(mDefaultTextColor);
- }
- } else if (child instanceof ViewGroup) {
- processChildrenTextColor((ViewGroup) child);
+ private void processTextColorRecursive(View view) {
+ if (view instanceof TextView) {
+ TextView textView = (TextView) view;
+ int foreground = textView.getCurrentTextColor();
+ if (foreground == mLightTextColor || foreground == mDarkTextColor) {
+ textView.setTextColor(mDefaultTextColor);
+ }
+ } else if (view instanceof ViewGroup) {
+ ViewGroup viewGroup = (ViewGroup) view;
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ processTextColorRecursive(viewGroup.getChildAt(i));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 2ce4037..d638019 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -89,7 +89,8 @@
private int mNotificationStackHeight;
/**
- * Minimum top margin to avoid overlap with status bar.
+ * Minimum top margin to avoid overlap with status bar, lock icon, or multi-user switcher
+ * avatar.
*/
private int mMinTopMargin;
@@ -186,15 +187,15 @@
/**
* Sets up algorithm values.
*/
- public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
- float panelExpansion, int parentHeight, int keyguardStatusHeight,
- int userSwitchHeight, int clockPreferredY, int userSwitchPreferredY,
- boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
- boolean bypassEnabled, int unlockedStackScrollerPadding, boolean showLockIcon,
- float qsExpansion, int cutoutTopInset) {
- mMinTopMargin = statusBarMinHeight + (showLockIcon
- ? mContainerTopPaddingWithLockIcon : mContainerTopPaddingWithoutLockIcon)
- + userSwitchHeight;
+ public void setup(int keyguardStatusBarHeaderHeight, int maxShadeBottom,
+ int notificationStackHeight, float panelExpansion, int parentHeight,
+ int keyguardStatusHeight, int userSwitchHeight, int clockPreferredY,
+ int userSwitchPreferredY, boolean hasCustomClock, boolean hasVisibleNotifs, float dark,
+ float emptyDragAmount, boolean bypassEnabled, int unlockedStackScrollerPadding,
+ boolean showLockIcon, float qsExpansion, int cutoutTopInset) {
+ mMinTopMargin = keyguardStatusBarHeaderHeight + Math.max(showLockIcon
+ ? mContainerTopPaddingWithLockIcon : mContainerTopPaddingWithoutLockIcon,
+ userSwitchHeight);
mMaxShadeBottom = maxShadeBottom;
mNotificationStackHeight = notificationStackHeight;
mPanelExpansion = panelExpansion;
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 6940050..093f57a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -287,21 +287,6 @@
}
};
- final KeyguardUserSwitcherController.KeyguardUserSwitcherListener
- mKeyguardUserSwitcherListener =
- new KeyguardUserSwitcherController.KeyguardUserSwitcherListener() {
- @Override
- public void onKeyguardUserSwitcherChanged(boolean open) {
- if (mKeyguardUserSwitcherController == null) {
- updateUserSwitcherVisibility(false);
- } else if (!mKeyguardUserSwitcherController.isSimpleUserSwitcher()) {
- updateUserSwitcherVisibility(open
- && mKeyguardStateController.isShowing()
- && !mKeyguardStateController.isKeyguardFadingAway());
- }
- }
- };
-
private final LayoutInflater mLayoutInflater;
private final PowerManager mPowerManager;
private final AccessibilityManager mAccessibilityManager;
@@ -329,7 +314,6 @@
private KeyguardAffordanceHelper mAffordanceHelper;
private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
- private boolean mKeyguardUserSwitcherIsShowing;
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
private KeyguardStatusBarView mKeyguardStatusBar;
private ViewGroup mBigClockContainer;
@@ -374,6 +358,7 @@
private ValueAnimator mQsExpansionAnimator;
private FlingAnimationUtils mFlingAnimationUtils;
private int mStatusBarMinHeight;
+ private int mStatusBarHeaderHeightKeyguard;
private int mNotificationsHeaderCollideDistance;
private float mEmptyDragAmount;
private float mDownX;
@@ -772,6 +757,8 @@
.setMaxLengthSeconds(0.4f).build();
mStatusBarMinHeight = mResources.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
+ mStatusBarHeaderHeightKeyguard = mResources.getDimensionPixelSize(
+ R.dimen.status_bar_header_height_keyguard);
mQsPeekHeight = mResources.getDimensionPixelSize(R.dimen.qs_peek_height);
mNotificationsHeaderCollideDistance = mResources.getDimensionPixelSize(
R.dimen.header_notifications_collide_distance);
@@ -808,7 +795,6 @@
// Try to close the switcher so that callbacks are triggered if necessary.
// Otherwise, NPV can get into a state where some of the views are still hidden
mKeyguardUserSwitcherController.closeSwitcherIfOpenAndNotSimple(false);
- mKeyguardUserSwitcherController.removeCallback();
}
mKeyguardQsUserSwitchController = null;
@@ -828,7 +814,6 @@
mKeyguardUserSwitcherComponentFactory.build(keyguardUserSwitcherView);
mKeyguardUserSwitcherController =
userSwitcherComponent.getKeyguardUserSwitcherController();
- mKeyguardUserSwitcherController.setCallback(mKeyguardUserSwitcherListener);
mKeyguardUserSwitcherController.init();
mKeyguardStatusBar.setKeyguardUserSwitcherEnabled(true);
} else {
@@ -1069,7 +1054,7 @@
int totalHeight = mView.getHeight();
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
int clockPreferredY = mKeyguardStatusViewController.getClockPreferredY(totalHeight);
- int userSwitcherPreferredY = mStatusBarMinHeight;
+ int userSwitcherPreferredY = mStatusBarHeaderHeightKeyguard;
boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
final boolean hasVisibleNotifications = mNotificationStackScrollLayoutController
.getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia();
@@ -1078,7 +1063,8 @@
? mKeyguardQsUserSwitchController.getUserIconHeight()
: (mKeyguardUserSwitcherController != null
? mKeyguardUserSwitcherController.getUserIconHeight() : 0);
- mClockPositionAlgorithm.setup(mStatusBarMinHeight, totalHeight - bottomPadding,
+ mClockPositionAlgorithm.setup(mStatusBarHeaderHeightKeyguard,
+ totalHeight - bottomPadding,
mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
getExpandedFraction(),
totalHeight,
@@ -3523,34 +3509,6 @@
return false;
}
- private void updateUserSwitcherVisibility(boolean open) {
- // Do not update if previously called with the same state.
- if (mKeyguardUserSwitcherIsShowing == open) {
- return;
- }
- mKeyguardUserSwitcherIsShowing = open;
-
- if (open) {
- animateKeyguardStatusBarOut();
- mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
- mBarState,
- true /* keyguardFadingAway */,
- true /* goingToFullShade */,
- mBarState);
- setKeyguardBottomAreaVisibility(mBarState, true);
- mNotificationContainerParent.setVisibility(View.GONE);
- } else {
- animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
- StatusBarState.KEYGUARD,
- false,
- false,
- StatusBarState.SHADE_LOCKED);
- setKeyguardBottomAreaVisibility(mBarState, false);
- mNotificationContainerParent.setVisibility(View.VISIBLE);
- }
- }
-
private void updateDisabledUdfpsController() {
final boolean udfpsEnrolled = mAuthController.getUdfpsRegion() != null
&& mAuthController.isUdfpsEnrolled(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 041a97e..b25fced 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -78,6 +78,7 @@
import android.metrics.LogMaker;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -276,7 +277,8 @@
public static final boolean DEBUG = false;
public static final boolean SPEW = false;
public static final boolean DUMPTRUCK = true; // extra dumpsys info
- public static final boolean DEBUG_GESTURES = false;
+ public static final boolean DEBUG_GESTURES = Build.IS_DEBUGGABLE; // TODO(b/178277858)
+ public static final boolean DEBUG_GESTURES_VERBOSE = true;
public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
public static final boolean DEBUG_CAMERA_LIFT = false;
@@ -456,9 +458,7 @@
private final DisplayMetrics mDisplayMetrics;
// XXX: gesture research
- private final GestureRecorder mGestureRec = DEBUG_GESTURES
- ? new GestureRecorder("/sdcard/statusbar_gestures.dat")
- : null;
+ private GestureRecorder mGestureRec = null;
private final ScreenPinningRequest mScreenPinningRequest;
@@ -856,6 +856,10 @@
mActivityIntentHelper = new ActivityIntentHelper(mContext);
DateTimeView.setReceiverHandler(timeTickHandler);
+
+ if (DEBUG_GESTURES) {
+ mGestureRec = new GestureRecorder(mContext.getCacheDir() + "/statusbar_gestures.dat");
+ }
}
@Override
@@ -2267,7 +2271,7 @@
public boolean interceptTouchEvent(MotionEvent event) {
if (DEBUG_GESTURES) {
- if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
+ if (DEBUG_GESTURES_VERBOSE || event.getActionMasked() != MotionEvent.ACTION_MOVE) {
EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH,
event.getActionMasked(), (int) event.getX(), (int) event.getY(),
mDisabled1, mDisabled2);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
index a76d08a..7f935d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyController.java
@@ -16,17 +16,17 @@
package com.android.systemui.statusbar.policy;
-import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
public interface IndividualSensorPrivacyController extends
CallbackController<IndividualSensorPrivacyController.Callback> {
void init();
- boolean isSensorBlocked(@IndividualSensor int sensor);
+ boolean isSensorBlocked(@Sensor int sensor);
- void setSensorBlocked(@IndividualSensor int sensor, boolean blocked);
+ void setSensorBlocked(@Sensor int sensor, boolean blocked);
interface Callback {
- void onSensorBlockedChanged(@IndividualSensor int sensor, boolean blocked);
+ void onSensorBlockedChanged(@Sensor 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
index 32d15ed..295df05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IndividualSensorPrivacyControllerImpl.java
@@ -16,11 +16,11 @@
package com.android.systemui.statusbar.policy;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import android.hardware.SensorPrivacyManager;
-import android.hardware.SensorPrivacyManager.IndividualSensor;
+import android.hardware.SensorPrivacyManager.Sensors.Sensor;
import android.util.ArraySet;
import android.util.SparseBooleanArray;
@@ -30,8 +30,7 @@
public class IndividualSensorPrivacyControllerImpl implements IndividualSensorPrivacyController {
- private static final int[] SENSORS = new int[] {INDIVIDUAL_SENSOR_CAMERA,
- INDIVIDUAL_SENSOR_MICROPHONE};
+ private static final int[] SENSORS = new int[] {CAMERA, MICROPHONE};
private final @NonNull SensorPrivacyManager mSensorPrivacyManager;
private final SparseBooleanArray mState = new SparseBooleanArray();
@@ -48,18 +47,18 @@
mSensorPrivacyManager.addSensorPrivacyListener(sensor,
(enabled) -> onSensorPrivacyChanged(sensor, enabled));
- mState.put(sensor, mSensorPrivacyManager.isIndividualSensorPrivacyEnabled(sensor));
+ mState.put(sensor, mSensorPrivacyManager.isSensorPrivacyEnabled(sensor));
}
}
@Override
- public boolean isSensorBlocked(@IndividualSensor int sensor) {
+ public boolean isSensorBlocked(@Sensor int sensor) {
return mState.get(sensor, false);
}
@Override
- public void setSensorBlocked(@IndividualSensor int sensor, boolean blocked) {
- mSensorPrivacyManager.setIndividualSensorPrivacyForProfileGroup(sensor, blocked);
+ public void setSensorBlocked(@Sensor int sensor, boolean blocked) {
+ mSensorPrivacyManager.setSensorPrivacyForProfileGroup(sensor, blocked);
}
@Override
@@ -72,7 +71,7 @@
mCallbacks.remove(listener);
}
- private void onSensorPrivacyChanged(@IndividualSensor int sensor, boolean blocked) {
+ private void onSensorPrivacyChanged(@Sensor int sensor, boolean blocked) {
mState.put(sensor, blocked);
for (Callback callback : mCallbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
index b76e451..8845a05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
@@ -19,9 +19,13 @@
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.database.DataSetObserver;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.UserHandle;
@@ -50,7 +54,6 @@
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.ViewController;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
import javax.inject.Inject;
@@ -73,9 +76,10 @@
private final KeyguardUserAdapter mAdapter;
private final KeyguardStateController mKeyguardStateController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
- private WeakReference<KeyguardUserSwitcherListener> mKeyguardUserSwitcherCallback;
protected final SysuiStatusBarStateController mStatusBarStateController;
private final KeyguardVisibilityHelper mKeyguardVisibilityHelper;
+ private ObjectAnimator mBgAnimator;
+ private final KeyguardUserSwitcherScrim mBackground;
// Child views of KeyguardUserSwitcherView
private KeyguardUserSwitcherListView mListView;
@@ -171,6 +175,7 @@
mUserSwitcherController, this);
mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView,
keyguardStateController, dozeParameters);
+ mBackground = new KeyguardUserSwitcherScrim(context);
}
@Override
@@ -204,6 +209,9 @@
mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
mStatusBarStateController.addCallback(mStatusBarStateListener);
mScreenLifecycle.addObserver(mScreenObserver);
+ mView.addOnLayoutChangeListener(mBackground);
+ mView.setBackground(mBackground);
+ mBackground.setAlpha(0);
}
@Override
@@ -217,6 +225,9 @@
mKeyguardUpdateMonitor.removeCallback(mInfoCallback);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
mScreenLifecycle.removeObserver(mScreenObserver);
+ mView.removeOnLayoutChangeListener(mBackground);
+ mView.setBackground(null);
+ mBackground.setAlpha(0);
}
/**
@@ -338,6 +349,13 @@
animate);
PropertyAnimator.setProperty(mListView, AnimatableProperty.TRANSLATION_X, -Math.abs(x),
ANIMATION_PROPERTIES, animate);
+
+ Rect r = new Rect();
+ mListView.getDrawingRect(r);
+ mView.offsetDescendantRectToMyCoords(mListView, r);
+ mBackground.setGradientCenter(
+ (int) (mListView.getTranslationX() + r.left + r.width() / 2),
+ (int) (mListView.getTranslationY() + r.top + r.height() / 2));
}
/**
@@ -372,49 +390,52 @@
}
/**
- * Remove the callback if it exists.
- */
- public void removeCallback() {
- if (DEBUG) Log.d(TAG, "removeCallback");
- mKeyguardUserSwitcherCallback = null;
- }
-
- /**
- * Register to receive notifications about keyguard user switcher state
- * (see {@link KeyguardUserSwitcherListener}.
- *
- * Only one callback can be used at a time.
- *
- * @param callback The callback to register
- */
- public void setCallback(KeyguardUserSwitcherListener callback) {
- if (DEBUG) Log.d(TAG, "setCallback");
- mKeyguardUserSwitcherCallback = new WeakReference<>(callback);
- }
-
- /**
- * If user switcher state changes, notifies all {@link KeyguardUserSwitcherListener}.
- * Switcher state is updatd before animations finish.
+ * NOTE: switcher state is updated before animations finish.
*
* @param animate true to animate transition. The user switcher state (i.e.
* {@link #isUserSwitcherOpen()}) is updated before animation is finished.
*/
private void setUserSwitcherOpened(boolean open, boolean animate) {
- boolean wasOpen = mUserSwitcherOpen;
if (DEBUG) {
- Log.d(TAG, String.format("setUserSwitcherOpened: %b -> %b (animate=%b)", wasOpen,
- open, animate));
+ Log.d(TAG,
+ String.format("setUserSwitcherOpened: %b -> %b (animate=%b)",
+ mUserSwitcherOpen, open, animate));
}
mUserSwitcherOpen = open;
- if (mUserSwitcherOpen != wasOpen) {
- notifyUserSwitcherStateChanged();
- }
updateVisibilities(animate);
}
private void updateVisibilities(boolean animate) {
if (DEBUG) Log.d(TAG, String.format("updateVisibilities: animate=%b", animate));
mEndGuestButton.animate().cancel();
+ if (mBgAnimator != null) {
+ mBgAnimator.cancel();
+ }
+
+ if (mUserSwitcherOpen) {
+ mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255);
+ mBgAnimator.setDuration(400);
+ mBgAnimator.setInterpolator(Interpolators.ALPHA_IN);
+ mBgAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mBgAnimator = null;
+ }
+ });
+ mBgAnimator.start();
+ } else {
+ mBgAnimator = ObjectAnimator.ofInt(mBackground, "alpha", 255, 0);
+ mBgAnimator.setDuration(400);
+ mBgAnimator.setInterpolator(Interpolators.ALPHA_OUT);
+ mBgAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mBgAnimator = null;
+ }
+ });
+ mBgAnimator.start();
+ }
+
if (mUserSwitcherOpen && mCurrentUserIsGuest) {
// Show the "End guest session" button
mEndGuestButton.setVisibility(View.VISIBLE);
@@ -459,34 +480,6 @@
return mUserSwitcherOpen;
}
- private void notifyUserSwitcherStateChanged() {
- if (DEBUG) {
- Log.d(TAG, String.format("notifyUserSwitcherStateChanged: mUserSwitcherOpen=%b",
- mUserSwitcherOpen));
- }
- if (mKeyguardUserSwitcherCallback != null) {
- KeyguardUserSwitcherListener cb = mKeyguardUserSwitcherCallback.get();
- if (cb != null) {
- cb.onKeyguardUserSwitcherChanged(mUserSwitcherOpen);
- }
- }
- }
-
- /**
- * Callback for keyguard user switcher state information
- */
- public interface KeyguardUserSwitcherListener {
-
- /**
- * Called when the keyguard enters or leaves user switcher mode. This will be called
- * before the animations are finished.
- *
- * @param open if true, keyguard is showing the user switcher or transitioning from/to user
- * switcher mode.
- */
- void onKeyguardUserSwitcherChanged(boolean open);
- }
-
static class KeyguardUserAdapter extends
UserSwitcherController.BaseUserAdapter implements View.OnClickListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
index 49f5bcd..1d9d33d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherScrim.java
@@ -26,7 +26,6 @@
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
-import android.util.LayoutDirection;
import android.view.View;
import com.android.systemui.R;
@@ -38,13 +37,14 @@
implements View.OnLayoutChangeListener {
private static final float OUTER_EXTENT = 2.5f;
- private static final float INNER_EXTENT = 0.75f;
+ private static final float INNER_EXTENT = 0.25f;
private int mDarkColor;
- private int mTop;
private int mAlpha = 255;
private Paint mRadialGradientPaint = new Paint();
- private int mLayoutWidth;
+ private int mCircleX;
+ private int mCircleY;
+ private int mSize;
public KeyguardUserSwitcherScrim(Context context) {
mDarkColor = context.getColor(
@@ -53,14 +53,11 @@
@Override
public void draw(Canvas canvas) {
- boolean isLtr = getLayoutDirection() == LayoutDirection.LTR;
+ if (mAlpha == 0) {
+ return;
+ }
Rect bounds = getBounds();
- float width = bounds.width() * OUTER_EXTENT;
- float height = (mTop + bounds.height()) * OUTER_EXTENT;
- canvas.translate(0, -mTop);
- canvas.scale(1, height / width);
- canvas.drawRect(isLtr ? bounds.right - width : 0, 0,
- isLtr ? bounds.right : bounds.left + width, width, mRadialGradientPaint);
+ canvas.drawRect(bounds.left, bounds.top, bounds.right, bounds.bottom, mRadialGradientPaint);
}
@Override
@@ -88,24 +85,36 @@
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) {
- mLayoutWidth = right - left;
- mTop = top;
+ int width = right - left;
+ int height = bottom - top;
+ mSize = Math.max(width, height);
updatePaint();
}
}
private void updatePaint() {
- if (mLayoutWidth == 0) {
+ if (mSize == 0) {
return;
}
- float radius = mLayoutWidth * OUTER_EXTENT;
- boolean isLtr = getLayoutDirection() == LayoutDirection.LTR;
+ float outerRadius = mSize * OUTER_EXTENT;
mRadialGradientPaint.setShader(
- new RadialGradient(isLtr ? mLayoutWidth : 0, 0, radius,
+ new RadialGradient(mCircleX, mCircleY, outerRadius,
new int[] { Color.argb(
(int) (Color.alpha(mDarkColor) * mAlpha / 255f), 0, 0, 0),
Color.TRANSPARENT },
- new float[] { Math.max(0f, mLayoutWidth * INNER_EXTENT / radius), 1f },
+ new float[] { Math.max(0f, INNER_EXTENT / OUTER_EXTENT), 1f },
Shader.TileMode.CLAMP));
}
+
+ /**
+ * Sets the center of the radial gradient used as a background
+ *
+ * @param x
+ * @param y
+ */
+ public void setGradientCenter(int x, int y) {
+ mCircleX = x;
+ mCircleY = y;
+ updatePaint();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
index 0a3e833..bbb2f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java
@@ -94,6 +94,7 @@
*/
static final List<String> THEME_CATEGORIES = Lists.newArrayList(
OVERLAY_CATEGORY_SYSTEM_PALETTE,
+ OVERLAY_CATEGORY_NEUTRAL_PALETTE,
OVERLAY_CATEGORY_ICON_LAUNCHER,
OVERLAY_CATEGORY_SHAPE,
OVERLAY_CATEGORY_FONT,
@@ -107,6 +108,7 @@
@VisibleForTesting
static final Set<String> SYSTEM_USER_CATEGORIES = Sets.newHashSet(
OVERLAY_CATEGORY_SYSTEM_PALETTE,
+ OVERLAY_CATEGORY_NEUTRAL_PALETTE,
OVERLAY_CATEGORY_ACCENT_COLOR,
OVERLAY_CATEGORY_FONT,
OVERLAY_CATEGORY_SHAPE,
@@ -129,8 +131,9 @@
mLauncherPackage = launcherPackage;
mThemePickerPackage = themePickerPackage;
mTargetPackageToCategories.put(ANDROID_PACKAGE, Sets.newHashSet(
- OVERLAY_CATEGORY_SYSTEM_PALETTE, OVERLAY_CATEGORY_ACCENT_COLOR,
- OVERLAY_CATEGORY_FONT, OVERLAY_CATEGORY_SHAPE, OVERLAY_CATEGORY_ICON_ANDROID));
+ OVERLAY_CATEGORY_SYSTEM_PALETTE, OVERLAY_CATEGORY_NEUTRAL_PALETTE,
+ OVERLAY_CATEGORY_ACCENT_COLOR, OVERLAY_CATEGORY_FONT, OVERLAY_CATEGORY_SHAPE,
+ OVERLAY_CATEGORY_ICON_ANDROID));
mTargetPackageToCategories.put(SYSUI_PACKAGE,
Sets.newHashSet(OVERLAY_CATEGORY_ICON_SYSUI));
mTargetPackageToCategories.put(SETTINGS_PACKAGE,
@@ -158,10 +161,10 @@
void applyCurrentUserOverlays(
Map<String, OverlayIdentifier> categoryToPackage,
FabricatedOverlay[] pendingCreation,
- Set<UserHandle> userHandles) {
+ int currentUser,
+ Set<UserHandle> managedProfiles) {
// Disable all overlays that have not been specified in the user setting.
final Set<String> overlayCategoriesToDisable = new HashSet<>(THEME_CATEGORIES);
- overlayCategoriesToDisable.removeAll(categoryToPackage.keySet());
final Set<String> targetPackagesToQuery = overlayCategoriesToDisable.stream()
.map(category -> mCategoryToTargetPackage.get(category))
.collect(Collectors.toSet());
@@ -172,6 +175,7 @@
.filter(o ->
mTargetPackageToCategories.get(o.targetPackageName).contains(o.category))
.filter(o -> overlayCategoriesToDisable.contains(o.category))
+ .filter(o -> !categoryToPackage.containsValue(new OverlayIdentifier(o.packageName)))
.filter(o -> o.isEnabled())
.map(o -> new Pair<>(o.category, o.packageName))
.collect(Collectors.toList());
@@ -183,17 +187,18 @@
}
}
- // Toggle overlays in the order of THEME_CATEGORIES.
+ for (Pair<String, String> packageToDisable : overlaysToDisable) {
+ OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
+ setEnabled(transaction, overlayInfo, packageToDisable.first, currentUser,
+ managedProfiles, false);
+ }
+
for (String category : THEME_CATEGORIES) {
if (categoryToPackage.containsKey(category)) {
OverlayIdentifier overlayInfo = categoryToPackage.get(category);
- setEnabled(transaction, overlayInfo, category, userHandles, true);
+ setEnabled(transaction, overlayInfo, category, currentUser, managedProfiles, true);
}
}
- for (Pair<String, String> packageToDisable : overlaysToDisable) {
- OverlayIdentifier overlayInfo = new OverlayIdentifier(packageToDisable.second);
- setEnabled(transaction, overlayInfo, packageToDisable.first, userHandles, false);
- }
mExecutor.execute(() -> {
try {
@@ -210,18 +215,30 @@
}
private void setEnabled(OverlayManagerTransaction.Builder transaction,
- OverlayIdentifier identifier, String category, Set<UserHandle> handles,
- boolean enabled) {
+ OverlayIdentifier identifier, String category, int currentUser,
+ Set<UserHandle> managedProfiles, boolean enabled) {
if (DEBUG) {
Log.d(TAG, "setEnabled: " + identifier.getPackageName() + " category: "
+ category + ": " + enabled);
}
- for (UserHandle userHandle : handles) {
- transaction.setEnabled(identifier, enabled, userHandle.getIdentifier());
- }
- if (!handles.contains(UserHandle.SYSTEM) && SYSTEM_USER_CATEGORIES.contains(category)) {
+
+ transaction.setEnabled(identifier, enabled, currentUser);
+ if (currentUser != UserHandle.SYSTEM.getIdentifier()
+ && SYSTEM_USER_CATEGORIES.contains(category)) {
transaction.setEnabled(identifier, enabled, UserHandle.SYSTEM.getIdentifier());
}
+
+ // Do not apply Launcher or Theme picker overlays to managed users. Apps are not
+ // installed in there.
+ OverlayInfo overlayInfo = mOverlayManager.getOverlayInfo(identifier, UserHandle.SYSTEM);
+ if (overlayInfo == null || overlayInfo.targetPackageName.equals(mLauncherPackage)
+ || overlayInfo.targetPackageName.equals(mThemePickerPackage)) {
+ return;
+ }
+
+ for (UserHandle userHandle : managedProfiles) {
+ transaction.setEnabled(identifier, enabled, userHandle.getIdentifier());
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 1f222d8..5d02845 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -55,14 +55,13 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.settings.SecureSettings;
-import com.google.android.collect.Sets;
-
import org.json.JSONException;
import org.json.JSONObject;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collection;
+import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -86,7 +85,7 @@
protected static final int PRIMARY = 0;
protected static final int SECONDARY = 1;
- protected static final int NEUTRAL = 1;
+ protected static final int NEUTRAL = 2;
// If lock screen wallpaper colors should also be considered when selecting the theme.
// Doing this has performance impact, given that overlays would need to be swapped when
@@ -151,7 +150,7 @@
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
- updateThemeOverlays();
+ reevaluateSystemTheme(true /* forceReload */);
}
}, filter, mBgExecutor, UserHandle.ALL);
mSecureSettings.registerContentObserverForUser(
@@ -163,7 +162,7 @@
int userId) {
if (DEBUG) Log.d(TAG, "Overlay changed for user: " + userId);
if (ActivityManager.getCurrentUser() == userId) {
- updateThemeOverlays();
+ reevaluateSystemTheme(true /* forceReload */);
}
}
},
@@ -180,7 +179,7 @@
mLockColors = lockColors;
}
mSystemColors = systemColor;
- reevaluateSystemTheme();
+ reevaluateSystemTheme(false /* forceReload */);
});
});
if (USE_LOCK_SCREEN_WALLPAPER) {
@@ -192,7 +191,7 @@
}
// It's possible that the user has a lock screen wallpaper. On this case we'll
// end up with different colors after unlocking.
- reevaluateSystemTheme();
+ reevaluateSystemTheme(false /* forceReload */);
}
});
}
@@ -209,11 +208,11 @@
Log.d(TAG, "got new lock colors: " + wallpaperColors + " where: " + which);
}
}
- reevaluateSystemTheme();
+ reevaluateSystemTheme(false /* forceReload */);
}, null, UserHandle.USER_ALL);
}
- private void reevaluateSystemTheme() {
+ private void reevaluateSystemTheme(boolean forceReload) {
WallpaperColors currentColors =
mKeyguardStateController.isShowing() && mLockColors != null
? mLockColors : mSystemColors;
@@ -228,7 +227,8 @@
accentCandidate = getAccentColor(currentColors);
}
- if (mMainWallpaperColor == mainColor && mWallpaperAccentColor == accentCandidate) {
+ if (mMainWallpaperColor == mainColor && mWallpaperAccentColor == accentCandidate
+ && !forceReload) {
return;
}
@@ -309,6 +309,16 @@
} catch (NumberFormatException e) {
Log.w(TAG, "Invalid color definition: " + systemPalette.getPackageName());
}
+ } else if (!mIsMonetEnabled && systemPalette != null) {
+ try {
+ // It's possible that we flipped the flag off and still have a @ColorInt in the
+ // setting. We need to sanitize the input, otherwise the overlay transaction will
+ // fail.
+ Integer.parseInt(systemPalette.getPackageName().toLowerCase(), 16);
+ categoryToPackage.remove(OVERLAY_CATEGORY_SYSTEM_PALETTE);
+ } catch (NumberFormatException e) {
+ // This is a package name. All good, let's continue
+ }
}
// Same for accent color.
@@ -322,6 +332,13 @@
} catch (NumberFormatException e) {
Log.w(TAG, "Invalid color definition: " + accentPalette.getPackageName());
}
+ } else if (!mIsMonetEnabled && accentPalette != null) {
+ try {
+ Integer.parseInt(accentPalette.getPackageName().toLowerCase(), 16);
+ categoryToPackage.remove(OVERLAY_CATEGORY_ACCENT_COLOR);
+ } catch (NumberFormatException e) {
+ // This is a package name. All good, let's continue
+ }
}
// Compatibility with legacy themes, where full packages were defined, instead of just
@@ -337,10 +354,10 @@
categoryToPackage.put(OVERLAY_CATEGORY_ACCENT_COLOR, mSecondaryOverlay.getIdentifier());
}
- Set<UserHandle> userHandles = Sets.newHashSet(UserHandle.of(currentUser));
+ Set<UserHandle> managedProfiles = new HashSet<>();
for (UserInfo userInfo : mUserManager.getEnabledProfiles(currentUser)) {
if (userInfo.isManagedProfile()) {
- userHandles.add(userInfo.getUserHandle());
+ managedProfiles.add(userInfo.getUserHandle());
}
}
if (DEBUG) {
@@ -352,9 +369,10 @@
mNeedsOverlayCreation = false;
mThemeManager.applyCurrentUserOverlays(categoryToPackage, new FabricatedOverlay[] {
mPrimaryOverlay, mSecondaryOverlay, mNeutralOverlay
- }, userHandles);
+ }, currentUser, managedProfiles);
} else {
- mThemeManager.applyCurrentUserOverlays(categoryToPackage, null, userHandles);
+ mThemeManager.applyCurrentUserOverlays(categoryToPackage, null, currentUser,
+ managedProfiles);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 5d94659..4611fe03 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -31,6 +31,7 @@
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.R;
import com.android.systemui.dagger.WMComponent;
import com.android.systemui.dagger.WMSingleton;
import com.android.systemui.dagger.qualifiers.Main;
@@ -97,7 +98,12 @@
@Module
public abstract class WMShellBaseModule {
- private static final boolean ENABLE_SHELL_MAIN_THREAD = false;
+ /**
+ * Returns whether to enable a separate shell thread for the shell features.
+ */
+ private static boolean enableShellMainThread(Context context) {
+ return context.getResources().getBoolean(R.bool.config_enableShellMainThread);
+ }
//
// Shell Concurrency - Components used for managing threading in the Shell and SysUI
@@ -120,8 +126,8 @@
@WMSingleton
@Provides
@ShellMainThread
- public static Handler provideShellMainHandler(@Main Handler sysuiMainHandler) {
- if (ENABLE_SHELL_MAIN_THREAD) {
+ public static Handler provideShellMainHandler(Context context, @Main Handler sysuiMainHandler) {
+ if (enableShellMainThread(context)) {
HandlerThread mainThread = new HandlerThread("wmshell.main");
mainThread.start();
return mainThread.getThreadHandler();
@@ -135,9 +141,9 @@
@WMSingleton
@Provides
@ShellMainThread
- public static ShellExecutor provideShellMainExecutor(@ShellMainThread Handler mainHandler,
- @Main ShellExecutor sysuiMainExecutor) {
- if (ENABLE_SHELL_MAIN_THREAD) {
+ public static ShellExecutor provideShellMainExecutor(Context context,
+ @ShellMainThread Handler mainHandler, @Main ShellExecutor sysuiMainExecutor) {
+ if (enableShellMainThread(context)) {
return new HandlerExecutor(mainHandler);
}
return sysuiMainExecutor;
@@ -409,10 +415,11 @@
ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, Context context,
RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
- @ShellMainThread ShellExecutor mainExecutor) {
+ @ShellMainThread ShellExecutor mainExecutor,
+ DisplayImeController displayImeController) {
if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
- rootTaskDisplayAreaOrganizer, mainExecutor));
+ rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController));
} else {
return Optional.empty();
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 997b488..754b6a6 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -104,9 +104,10 @@
@Provides
static AppPairsController provideAppPairs(ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, DisplayController displayController,
- @ShellMainThread ShellExecutor mainExecutor) {
+ @ShellMainThread ShellExecutor mainExecutor,
+ DisplayImeController displayImeController) {
return new AppPairsController(shellTaskOrganizer, syncQueue, displayController,
- mainExecutor);
+ mainExecutor, displayImeController);
}
//
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 14b4d02..854be1f 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -26,16 +26,11 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
-import android.testing.TestableResources;
-import android.view.View;
-import android.view.ViewGroup;
import android.view.WindowInsetsController;
-import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
@@ -50,21 +45,12 @@
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerTest extends SysuiTestCase {
- private static final int SCREEN_WIDTH = 1600;
- private static final int FAKE_MEASURE_SPEC =
- View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH, View.MeasureSpec.EXACTLY);
-
- private static final SecurityMode ONE_HANDED_SECURITY_MODE = SecurityMode.PIN;
- private static final SecurityMode TWO_HANDED_SECURITY_MODE = SecurityMode.Password;
-
-
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
@Mock
private WindowInsetsController mWindowInsetsController;
-
@Mock
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
@@ -72,18 +58,9 @@
@Before
public void setup() {
- // Needed here, otherwise when mKeyguardSecurityContainer is created below, it'll cache
- // the real references (rather than the TestableResources that this call creates).
- mContext.ensureTestableResources();
- FrameLayout.LayoutParams securityViewFlipperLayoutParams = new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
-
when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
- when(mSecurityViewFlipper.getLayoutParams()).thenReturn(securityViewFlipperLayoutParams);
mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
- mKeyguardSecurityContainer.addView(mSecurityViewFlipper, new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
@Test
@@ -92,75 +69,4 @@
verify(mWindowInsetsController).controlWindowInsetsAnimation(eq(ime()), anyLong(), any(),
any(), any());
}
-
- @Test
- public void onMeasure_usesFullWidthWithoutOneHandedMode() {
- setUpKeyguard(
- /* deviceConfigCanUseOneHandedKeyguard= */false,
- /* sysuiResourceCanUseOneHandedKeyguard= */ false,
- ONE_HANDED_SECURITY_MODE);
-
- mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
-
- verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
- }
-
- @Test
- public void onMeasure_usesFullWidthWithDeviceFlagDisabled() {
- setUpKeyguard(
- /* deviceConfigCanUseOneHandedKeyguard= */false,
- /* sysuiResourceCanUseOneHandedKeyguard= */ true,
- ONE_HANDED_SECURITY_MODE);
-
- mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
- verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
- }
-
- @Test
- public void onMeasure_usesFullWidthWithSysUIFlagDisabled() {
- setUpKeyguard(
- /* deviceConfigCanUseOneHandedKeyguard= */true,
- /* sysuiResourceCanUseOneHandedKeyguard= */ false,
- ONE_HANDED_SECURITY_MODE);
-
- mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
- verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
- }
-
- @Test
- public void onMeasure_usesHalfWidthWithFlagsEnabled() {
- setUpKeyguard(
- /* deviceConfigCanUseOneHandedKeyguard= */true,
- /* sysuiResourceCanUseOneHandedKeyguard= */ true,
- ONE_HANDED_SECURITY_MODE);
-
- int halfWidthMeasureSpec =
- View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH / 2, View.MeasureSpec.EXACTLY);
- mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
-
- verify(mSecurityViewFlipper).measure(halfWidthMeasureSpec, FAKE_MEASURE_SPEC);
- }
-
- @Test
- public void onMeasure_usesFullWidthForFullScreenIme() {
- setUpKeyguard(
- /* deviceConfigCanUseOneHandedKeyguard= */true,
- /* sysuiResourceCanUseOneHandedKeyguard= */ true,
- TWO_HANDED_SECURITY_MODE);
-
- mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
- verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
- }
-
- private void setUpKeyguard(
- boolean deviceConfigCanUseOneHandedKeyguard,
- boolean sysuiResourceCanUseOneHandedKeyguard,
- SecurityMode securityMode) {
- TestableResources testableResources = mContext.getOrCreateTestableResources();
- testableResources.addOverride(com.android.internal.R.bool.config_enableOneHandedKeyguard,
- deviceConfigCanUseOneHandedKeyguard);
- testableResources.addOverride(R.bool.can_use_one_handed_bouncer,
- sysuiResourceCanUseOneHandedKeyguard);
- mKeyguardSecurityContainer.updateLayoutForSecurityMode(securityMode);
- }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index 97cb873..2526990 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -16,8 +16,8 @@
package com.android.systemui.appops;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_CAMERA;
-import static android.hardware.SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static junit.framework.TestCase.assertFalse;
@@ -125,9 +125,9 @@
when(mAudioManager.getActiveRecordingConfigurations())
.thenReturn(List.of(mPausedMockRecording));
- when(mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA))
+ when(mSensorPrivacyController.isSensorBlocked(CAMERA))
.thenReturn(false);
- when(mSensorPrivacyController.isSensorBlocked(INDIVIDUAL_SENSOR_CAMERA))
+ when(mSensorPrivacyController.isSensorBlocked(CAMERA))
.thenReturn(false);
mController = new AppOpsControllerImpl(
@@ -505,7 +505,7 @@
assertFalse(list.get(0).isDisabled());
// Add a camera op, and disable the microphone. The camera op should be the only op returned
- mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_MICROPHONE, true);
+ mController.onSensorBlockedChanged(MICROPHONE, true);
mController.onOpActiveChanged(
AppOpsManager.OP_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages();
@@ -515,7 +515,7 @@
// Re enable the microphone, and verify the op returns
- mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_MICROPHONE, false);
+ mController.onSensorBlockedChanged(MICROPHONE, false);
mTestableLooper.processAllMessages();
list = mController.getActiveAppOps();
@@ -538,7 +538,7 @@
assertFalse(list.get(0).isDisabled());
// Add an audio op, and disable the camera. The audio op should be the only op returned
- mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_CAMERA, true);
+ mController.onSensorBlockedChanged(CAMERA, true);
mController.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mTestableLooper.processAllMessages();
@@ -547,7 +547,7 @@
assertEquals(AppOpsManager.OP_RECORD_AUDIO, list.get(0).getCode());
// Re enable the camera, and verify the op returns
- mController.onSensorBlockedChanged(INDIVIDUAL_SENSOR_CAMERA, false);
+ mController.onSensorBlockedChanged(CAMERA, false);
mTestableLooper.processAllMessages();
list = mController.getActiveAppOps();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index 0dfebab..a2a179e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -121,7 +121,6 @@
mQSTileHost, mQSCustomizerController, true, mMediaHost,
mQSTileRevealControllerFactory, mDumpManager, mMetricsLogger, mUiEventLogger,
mQSLogger, mBrightnessControllerFactory, mToggleSliderViewControllerFactory,
- /* labelsFlag */ false,
mFeatureFlags
);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 5870200..cb380d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -87,7 +87,6 @@
uiEventLogger,
qsLogger,
dumpManager,
- false,
featureFlags
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index ce0f122..9a5482c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -377,8 +377,6 @@
// THEN we send the dismissal to system server
verify(mStatusBarService).onNotificationClear(
notif2.sbn.getPackageName(),
- notif2.sbn.getTag(),
- 88,
notif2.sbn.getUser().getIdentifier(),
notif2.sbn.getKey(),
stats.dismissalSurface,
@@ -528,8 +526,6 @@
// THEN we never send the dismissal to system server
verify(mStatusBarService, never()).onNotificationClear(
notif.sbn.getPackageName(),
- notif.sbn.getTag(),
- 47,
notif.sbn.getUser().getIdentifier(),
notif.sbn.getKey(),
stats.dismissalSurface,
@@ -566,8 +562,6 @@
// THEN the notification is never sent to system server to dismiss
verify(mStatusBarService, never()).onNotificationClear(
eq(notif.sbn.getPackageName()),
- eq(notif.sbn.getTag()),
- eq(47),
eq(notif.sbn.getUser().getIdentifier()),
eq(notif.sbn.getKey()),
anyInt(),
@@ -596,8 +590,6 @@
// THEN we send the dismissal to system server
verify(mStatusBarService).onNotificationClear(
eq(notif.sbn.getPackageName()),
- eq(notif.sbn.getTag()),
- eq(47),
eq(notif.sbn.getUser().getIdentifier()),
eq(notif.sbn.getKey()),
anyInt(),
@@ -1125,8 +1117,6 @@
// THEN we send the dismissals to system server
verify(mStatusBarService).onNotificationClear(
notif1.sbn.getPackageName(),
- notif1.sbn.getTag(),
- 47,
notif1.sbn.getUser().getIdentifier(),
notif1.sbn.getKey(),
stats1.dismissalSurface,
@@ -1135,8 +1125,6 @@
verify(mStatusBarService).onNotificationClear(
notif2.sbn.getPackageName(),
- notif2.sbn.getTag(),
- 88,
notif2.sbn.getUser().getIdentifier(),
notif2.sbn.getKey(),
stats2.dismissalSurface,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java
index 45828c3..6067b42 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java
@@ -23,6 +23,7 @@
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_SETTINGS;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_SYSUI;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_THEME_PICKER;
+import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_NEUTRAL_PALETTE;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SHAPE;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SYSTEM_PALETTE;
import static com.android.systemui.theme.ThemeOverlayApplier.SETTINGS_PACKAGE;
@@ -31,7 +32,6 @@
import static com.android.systemui.theme.ThemeOverlayApplier.THEME_CATEGORIES;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
@@ -87,7 +87,9 @@
private static final String THEMEPICKER_PACKAGE = "com.android.wallpaper";
private static final String LAUNCHER_PACKAGE = "com.android.launcher3";
private static final UserHandle TEST_USER = UserHandle.of(5);
- private static final Set<UserHandle> TEST_USER_HANDLES = Sets.newHashSet(TEST_USER);
+ private static final UserHandle TEST_USER_MANAGED_PROFILE = UserHandle.of(6);
+ private static final Set<UserHandle> TEST_USER_HANDLES =
+ Sets.newHashSet(TEST_USER_MANAGED_PROFILE);
@Mock
OverlayManager mOverlayManager;
@@ -114,6 +116,8 @@
ANDROID_PACKAGE, OVERLAY_CATEGORY_ACCENT_COLOR, false),
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_SYSTEM_PALETTE,
ANDROID_PACKAGE, OVERLAY_CATEGORY_SYSTEM_PALETTE, false),
+ createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_NEUTRAL_PALETTE,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_NEUTRAL_PALETTE, false),
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_FONT,
ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT, false),
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_SHAPE,
@@ -124,6 +128,8 @@
ANDROID_PACKAGE, OVERLAY_CATEGORY_ACCENT_COLOR, true),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_SYSTEM_PALETTE,
ANDROID_PACKAGE, OVERLAY_CATEGORY_SYSTEM_PALETTE, true),
+ createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_NEUTRAL_PALETTE,
+ ANDROID_PACKAGE, OVERLAY_CATEGORY_NEUTRAL_PALETTE, true),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_FONT,
ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT, true),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_SHAPE,
@@ -154,13 +160,19 @@
THEMEPICKER_PACKAGE, OVERLAY_CATEGORY_ICON_THEME_PICKER, false),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_THEME_PICKER,
THEMEPICKER_PACKAGE, OVERLAY_CATEGORY_ICON_THEME_PICKER, true)));
+
+ OverlayInfo launcherTargetInfo = new OverlayInfo("packageName", LAUNCHER_PACKAGE,
+ null, null, "/", 0, 0, 0, false);
+ when(mOverlayManager.getOverlayInfo(any(OverlayIdentifier.class), any()))
+ .thenReturn(launcherTargetInfo);
clearInvocations(mOverlayManager);
verify(mDumpManager).registerDumpable(any(), any());
}
@Test
public void allCategoriesSpecified_allEnabledExclusively() {
- mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER_HANDLES);
+ mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
+ TEST_USER_HANDLES);
verify(mOverlayManager).commit(any());
for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) {
@@ -171,7 +183,8 @@
@Test
public void allCategoriesSpecified_sysuiCategoriesAlsoAppliedToSysuiUser() {
- mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER_HANDLES);
+ mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
+ TEST_USER_HANDLES);
for (Map.Entry<String, OverlayIdentifier> entry : ALL_CATEGORIES_MAP.entrySet()) {
if (SYSTEM_USER_CATEGORIES.contains(entry.getKey())) {
@@ -187,27 +200,25 @@
@Test
public void allCategoriesSpecified_enabledForAllUserHandles() {
Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES);
- UserHandle newUserHandle = UserHandle.of(10);
- userHandles.add(newUserHandle);
- mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, userHandles);
+ mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
+ userHandles);
for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) {
verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
eq(TEST_USER.getIdentifier()));
- verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
- eq(newUserHandle.getIdentifier()));
+ // Not enabled for work profile because the target package is LAUNCHER_PACKAGE
+ verify(mTransactionBuilder, never()).setEnabled(eq(overlayPackage), eq(true),
+ eq(TEST_USER_MANAGED_PROFILE.getIdentifier()));
}
}
@Test
public void applyCurrentUserOverlays_createsPendingOverlays() {
- Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES);
- UserHandle newUserHandle = UserHandle.of(10);
- userHandles.add(newUserHandle);
- FabricatedOverlay[] pendingCreation = new FabricatedOverlay[] {
+ FabricatedOverlay[] pendingCreation = new FabricatedOverlay[]{
mock(FabricatedOverlay.class)
};
- mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, pendingCreation, userHandles);
+ mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, pendingCreation,
+ TEST_USER.getIdentifier(), TEST_USER_HANDLES);
for (FabricatedOverlay overlay : pendingCreation) {
verify(mTransactionBuilder).registerFabricatedOverlay(eq(overlay));
@@ -215,20 +226,13 @@
}
@Test
- public void allCategoriesSpecified_overlayManagerNotQueried() {
- mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER_HANDLES);
-
- verify(mOverlayManager, never())
- .getOverlayInfosForTarget(anyString(), any(UserHandle.class));
- }
-
- @Test
public void someCategoriesSpecified_specifiedEnabled_unspecifiedDisabled() {
Map<String, OverlayIdentifier> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
categoryToPackage.remove(OVERLAY_CATEGORY_ICON_SETTINGS);
categoryToPackage.remove(OVERLAY_CATEGORY_ICON_ANDROID);
- mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER_HANDLES);
+ mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER.getIdentifier(),
+ TEST_USER_HANDLES);
for (OverlayIdentifier overlayPackage : categoryToPackage.values()) {
verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
@@ -244,7 +248,8 @@
@Test
public void zeroCategoriesSpecified_allDisabled() {
- mManager.applyCurrentUserOverlays(Maps.newArrayMap(), null, TEST_USER_HANDLES);
+ mManager.applyCurrentUserOverlays(Maps.newArrayMap(), null, TEST_USER.getIdentifier(),
+ TEST_USER_HANDLES);
for (String category : THEME_CATEGORIES) {
verify(mTransactionBuilder).setEnabled(
@@ -258,7 +263,8 @@
Map<String, OverlayIdentifier> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
categoryToPackage.put("blah.category", new OverlayIdentifier("com.example.blah.category"));
- mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER_HANDLES);
+ mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER.getIdentifier(),
+ TEST_USER_HANDLES);
verify(mTransactionBuilder, never()).setEnabled(
eq(new OverlayIdentifier("com.example.blah.category")), eq(false),
@@ -268,23 +274,6 @@
eq(TEST_USER.getIdentifier()));
}
- @Test
- public void overlayManagerOnlyQueriedForUnspecifiedPackages() {
- Map<String, OverlayIdentifier> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
- categoryToPackage.remove(OVERLAY_CATEGORY_ICON_SETTINGS);
-
- mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER_HANDLES);
-
- verify(mOverlayManager).getOverlayInfosForTarget(SETTINGS_PACKAGE, UserHandle.SYSTEM);
- verify(mOverlayManager, never()).getOverlayInfosForTarget(ANDROID_PACKAGE,
- UserHandle.SYSTEM);
- verify(mOverlayManager, never()).getOverlayInfosForTarget(SYSUI_PACKAGE, UserHandle.SYSTEM);
- verify(mOverlayManager, never()).getOverlayInfosForTarget(LAUNCHER_PACKAGE,
- UserHandle.SYSTEM);
- verify(mOverlayManager, never()).getOverlayInfosForTarget(THEMEPICKER_PACKAGE,
- UserHandle.SYSTEM);
- }
-
private static OverlayInfo createOverlayInfo(String packageName, String targetPackageName,
String category, boolean enabled) {
return new OverlayInfo(packageName, null, targetPackageName, null, category, "",
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index aa385ef..d80c40f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -143,7 +143,7 @@
ArgumentCaptor.forClass(Map.class);
verify(mThemeOverlayApplier)
- .applyCurrentUserOverlays(themeOverlays.capture(), any(), any());
+ .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any());
// Assert that we received the colors that we were expecting
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
@@ -175,7 +175,7 @@
ArgumentCaptor.forClass(Map.class);
verify(mThemeOverlayApplier)
- .applyCurrentUserOverlays(themeOverlays.capture(), any(), any());
+ .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any());
// Assert that we received the colors that we were expecting
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
@@ -198,7 +198,7 @@
ArgumentCaptor.forClass(Map.class);
verify(mThemeOverlayApplier)
- .applyCurrentUserOverlays(themeOverlays.capture(), any(), any());
+ .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any());
// Assert that we received the colors that we were expecting
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
diff --git a/packages/overlays/AccentColorAmethystOverlay/Android.bp b/packages/overlays/AccentColorAmethystOverlay/Android.bp
index 7519b12..186d770 100644
--- a/packages/overlays/AccentColorAmethystOverlay/Android.bp
+++ b/packages/overlays/AccentColorAmethystOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorAmethystOverlay",
theme: "AccentColorAmethyst",
diff --git a/packages/overlays/AccentColorAquamarineOverlay/Android.bp b/packages/overlays/AccentColorAquamarineOverlay/Android.bp
index 4469b36..7fd64f3 100644
--- a/packages/overlays/AccentColorAquamarineOverlay/Android.bp
+++ b/packages/overlays/AccentColorAquamarineOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorAquamarineOverlay",
theme: "AccentColorAquamarine",
diff --git a/packages/overlays/AccentColorBlackOverlay/Android.bp b/packages/overlays/AccentColorBlackOverlay/Android.bp
index bfee26e..ac923eb 100644
--- a/packages/overlays/AccentColorBlackOverlay/Android.bp
+++ b/packages/overlays/AccentColorBlackOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorBlackOverlay",
theme: "AccentColorBlack",
diff --git a/packages/overlays/AccentColorCarbonOverlay/Android.bp b/packages/overlays/AccentColorCarbonOverlay/Android.bp
index 47f66dd..f4f1b8b 100644
--- a/packages/overlays/AccentColorCarbonOverlay/Android.bp
+++ b/packages/overlays/AccentColorCarbonOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorCarbonOverlay",
theme: "AccentColorCarbon",
diff --git a/packages/overlays/AccentColorCinnamonOverlay/Android.bp b/packages/overlays/AccentColorCinnamonOverlay/Android.bp
index 8250315..53899bf 100644
--- a/packages/overlays/AccentColorCinnamonOverlay/Android.bp
+++ b/packages/overlays/AccentColorCinnamonOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorCinnamonOverlay",
theme: "AccentColorCinnamon",
diff --git a/packages/overlays/AccentColorGreenOverlay/Android.bp b/packages/overlays/AccentColorGreenOverlay/Android.bp
index 15b50c7..5b1f744 100644
--- a/packages/overlays/AccentColorGreenOverlay/Android.bp
+++ b/packages/overlays/AccentColorGreenOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorGreenOverlay",
theme: "AccentColorGreen",
diff --git a/packages/overlays/AccentColorOceanOverlay/Android.bp b/packages/overlays/AccentColorOceanOverlay/Android.bp
index 6ad63bc..a8588304 100644
--- a/packages/overlays/AccentColorOceanOverlay/Android.bp
+++ b/packages/overlays/AccentColorOceanOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorOceanOverlay",
theme: "AccentColorOcean",
diff --git a/packages/overlays/AccentColorOrchidOverlay/Android.bp b/packages/overlays/AccentColorOrchidOverlay/Android.bp
index b669333..31ed309 100644
--- a/packages/overlays/AccentColorOrchidOverlay/Android.bp
+++ b/packages/overlays/AccentColorOrchidOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorOrchidOverlay",
theme: "AccentColorOrchid",
diff --git a/packages/overlays/AccentColorPaletteOverlay/Android.bp b/packages/overlays/AccentColorPaletteOverlay/Android.bp
index eeefd16..a6cc1de 100644
--- a/packages/overlays/AccentColorPaletteOverlay/Android.bp
+++ b/packages/overlays/AccentColorPaletteOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorPaletteOverlay",
theme: "AccentColorPalette",
diff --git a/packages/overlays/AccentColorPurpleOverlay/Android.bp b/packages/overlays/AccentColorPurpleOverlay/Android.bp
index ead95df..80e0ab1 100644
--- a/packages/overlays/AccentColorPurpleOverlay/Android.bp
+++ b/packages/overlays/AccentColorPurpleOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorPurpleOverlay",
theme: "AccentColorPurple",
diff --git a/packages/overlays/AccentColorSandOverlay/Android.bp b/packages/overlays/AccentColorSandOverlay/Android.bp
index f70578a..771abca 100644
--- a/packages/overlays/AccentColorSandOverlay/Android.bp
+++ b/packages/overlays/AccentColorSandOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorSandOverlay",
theme: "AccentColorSand",
diff --git a/packages/overlays/AccentColorSpaceOverlay/Android.bp b/packages/overlays/AccentColorSpaceOverlay/Android.bp
index 1d713df..8e4abac 100644
--- a/packages/overlays/AccentColorSpaceOverlay/Android.bp
+++ b/packages/overlays/AccentColorSpaceOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorSpaceOverlay",
theme: "AccentColorSpace",
diff --git a/packages/overlays/AccentColorTangerineOverlay/Android.bp b/packages/overlays/AccentColorTangerineOverlay/Android.bp
index d3b1e54..75c708e 100644
--- a/packages/overlays/AccentColorTangerineOverlay/Android.bp
+++ b/packages/overlays/AccentColorTangerineOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "AccentColorTangerineOverlay",
theme: "AccentColorTangerine",
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.bp
index b8def987..8e03809 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "DisplayCutoutEmulationCornerOverlay",
theme: "DisplayCutoutEmulationCorner",
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.bp
index b64ddfd..afa5b64 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "DisplayCutoutEmulationDoubleOverlay",
theme: "DisplayCutoutEmulationDouble",
diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationHoleOverlay/Android.bp
index 86cfebf..eae907d 100644
--- a/packages/overlays/DisplayCutoutEmulationHoleOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "DisplayCutoutEmulationHoleOverlay",
theme: "DisplayCutoutEmulationHole",
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.bp
index 28ad9db..25bc676 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "DisplayCutoutEmulationNarrowOverlay",
theme: "DisplayCutoutEmulationNarrow",
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.bp
index cd00386..2828612 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "DisplayCutoutEmulationTallOverlay",
theme: "DisplayCutoutEmulationTall",
diff --git a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/Android.bp
index d5fe683..66be777 100644
--- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "DisplayCutoutEmulationWaterfallOverlay",
theme: "DisplayCutoutEmulationWaterfall",
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.bp b/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.bp
index 0157ec4..e71cefe 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.bp
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "DisplayCutoutEmulationWideOverlay",
theme: "DisplayCutoutEmulationWide",
diff --git a/packages/overlays/FontNotoSerifSourceOverlay/Android.bp b/packages/overlays/FontNotoSerifSourceOverlay/Android.bp
index 7fd145b..231295b 100644
--- a/packages/overlays/FontNotoSerifSourceOverlay/Android.bp
+++ b/packages/overlays/FontNotoSerifSourceOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "FontNotoSerifSourceOverlay",
theme: "FontNotoSerifSource",
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/Android.bp b/packages/overlays/IconPackCircularAndroidOverlay/Android.bp
index cd5829a..7040358 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackCircularAndroidOverlay",
theme: "IconPackCircularAndroid",
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/Android.bp b/packages/overlays/IconPackCircularLauncherOverlay/Android.bp
index 5f2491d..4f8b663 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackCircularLauncherOverlay",
theme: "IconPackCircularLauncher",
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/Android.bp b/packages/overlays/IconPackCircularSettingsOverlay/Android.bp
index d7bc657..93220c8 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackCircularSettingsOverlay",
theme: "IconPackCircularSettings",
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/Android.bp b/packages/overlays/IconPackCircularSystemUIOverlay/Android.bp
index 73b8cd8..4eaa420 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackCircularSystemUIOverlay",
theme: "IconPackCircularSystemUI",
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/Android.bp b/packages/overlays/IconPackCircularThemePickerOverlay/Android.bp
index 5063932..5105b79 100644
--- a/packages/overlays/IconPackCircularThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackCircularThemePickerOverlay",
theme: "IconPackCircularThemePicker",
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/Android.bp b/packages/overlays/IconPackFilledAndroidOverlay/Android.bp
index 83f3656..3c4025d 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackFilledAndroidOverlay",
theme: "IconPackFilledAndroid",
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/Android.bp b/packages/overlays/IconPackFilledLauncherOverlay/Android.bp
index 6ca2566..3c5078c 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackFilledLauncherOverlay",
theme: "IconPackFilledLauncher",
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/Android.bp b/packages/overlays/IconPackFilledSettingsOverlay/Android.bp
index 8551bd5..b5148c2 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackFilledSettingsOverlay",
theme: "IconPackFilledSettings",
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/Android.bp b/packages/overlays/IconPackFilledSystemUIOverlay/Android.bp
index 684deb4..eb040a5 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackFilledSystemUIOverlay",
theme: "IconPackFilledSystemUI",
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/Android.bp b/packages/overlays/IconPackFilledThemePickerOverlay/Android.bp
index dae378f..bee4808 100644
--- a/packages/overlays/IconPackFilledThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackFilledThemePickerOverlay",
theme: "IconPackFilledThemePicker",
diff --git a/packages/overlays/IconPackKaiAndroidOverlay/Android.bp b/packages/overlays/IconPackKaiAndroidOverlay/Android.bp
index 4161e25..ee588c1 100644
--- a/packages/overlays/IconPackKaiAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackKaiAndroidOverlay",
theme: "IconPackKaiAndroid",
diff --git a/packages/overlays/IconPackKaiLauncherOverlay/Android.bp b/packages/overlays/IconPackKaiLauncherOverlay/Android.bp
index 4bf8f11..dcdad7a 100644
--- a/packages/overlays/IconPackKaiLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackKaiLauncherOverlay",
theme: "IconPackKaiLauncher",
diff --git a/packages/overlays/IconPackKaiSettingsOverlay/Android.bp b/packages/overlays/IconPackKaiSettingsOverlay/Android.bp
index c43f9e5..974bb54 100644
--- a/packages/overlays/IconPackKaiSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackKaiSettingsOverlay",
theme: "IconPackKaiSettings",
diff --git a/packages/overlays/IconPackKaiSystemUIOverlay/Android.bp b/packages/overlays/IconPackKaiSystemUIOverlay/Android.bp
index 22a8c28..b04ca61 100644
--- a/packages/overlays/IconPackKaiSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackKaiSystemUIOverlay",
theme: "IconPackKaiSystemUI",
diff --git a/packages/overlays/IconPackKaiThemePickerOverlay/Android.bp b/packages/overlays/IconPackKaiThemePickerOverlay/Android.bp
index 85eb1c4..875cd1d 100644
--- a/packages/overlays/IconPackKaiThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackKaiThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackKaiThemePickerOverlay",
theme: "IconPackKaiThemePicker",
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/Android.bp b/packages/overlays/IconPackRoundedAndroidOverlay/Android.bp
index 948f015..cb7b013 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackRoundedAndroidOverlay",
theme: "IconPackRoundedAndroid",
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/Android.bp b/packages/overlays/IconPackRoundedLauncherOverlay/Android.bp
index 5fbe635..8ab6d95 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackRoundedLauncherOverlay",
theme: "IconPackRoundedLauncher",
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/Android.bp b/packages/overlays/IconPackRoundedSettingsOverlay/Android.bp
index b1a0713..ee2f98a9 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackRoundedSettingsOverlay",
theme: "IconPackRoundedSettings",
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/Android.bp b/packages/overlays/IconPackRoundedSystemUIOverlay/Android.bp
index 6432998..ee0220a 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackRoundedSystemUIOverlay",
theme: "IconPackRoundedSystemUI",
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/Android.bp b/packages/overlays/IconPackRoundedThemePickerOverlay/Android.bp
index 95e1d3a..d74765c 100644
--- a/packages/overlays/IconPackRoundedThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackRoundedThemePickerOverlay",
theme: "IconPackRoundedTheme",
diff --git a/packages/overlays/IconPackSamAndroidOverlay/Android.bp b/packages/overlays/IconPackSamAndroidOverlay/Android.bp
index e8c33b1..2e9dc34 100644
--- a/packages/overlays/IconPackSamAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackSamAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackSamAndroidOverlay",
theme: "IconPackSamAndroid",
diff --git a/packages/overlays/IconPackSamLauncherOverlay/Android.bp b/packages/overlays/IconPackSamLauncherOverlay/Android.bp
index a469646..aa0cf00 100644
--- a/packages/overlays/IconPackSamLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackSamLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackSamLauncherOverlay",
theme: "IconPackSamLauncher",
diff --git a/packages/overlays/IconPackSamSettingsOverlay/Android.bp b/packages/overlays/IconPackSamSettingsOverlay/Android.bp
index bc1fa45..a62037f 100644
--- a/packages/overlays/IconPackSamSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackSamSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackSamSettingsOverlay",
theme: "IconPackSamSettings",
diff --git a/packages/overlays/IconPackSamSystemUIOverlay/Android.bp b/packages/overlays/IconPackSamSystemUIOverlay/Android.bp
index db77352..96ba7a0 100644
--- a/packages/overlays/IconPackSamSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackSamSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackSamSystemUIOverlay",
theme: "IconPackSamSystemUI",
diff --git a/packages/overlays/IconPackSamThemePickerOverlay/Android.bp b/packages/overlays/IconPackSamThemePickerOverlay/Android.bp
index c216868..7376f03 100644
--- a/packages/overlays/IconPackSamThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackSamThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackSamThemePickerOverlay",
theme: "IconPackSamThemePicker",
diff --git a/packages/overlays/IconPackVictorAndroidOverlay/Android.bp b/packages/overlays/IconPackVictorAndroidOverlay/Android.bp
index de62af1..ee73778 100644
--- a/packages/overlays/IconPackVictorAndroidOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorAndroidOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackVictorAndroidOverlay",
theme: "IconPackVictorAndroid",
diff --git a/packages/overlays/IconPackVictorLauncherOverlay/Android.bp b/packages/overlays/IconPackVictorLauncherOverlay/Android.bp
index fc4c360..a0cd45a 100644
--- a/packages/overlays/IconPackVictorLauncherOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorLauncherOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackVictorLauncherOverlay",
theme: "IconPackVictorLauncher",
diff --git a/packages/overlays/IconPackVictorSettingsOverlay/Android.bp b/packages/overlays/IconPackVictorSettingsOverlay/Android.bp
index 046bb3d..7807c6b 100644
--- a/packages/overlays/IconPackVictorSettingsOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorSettingsOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackVictorSettingsOverlay",
theme: "IconPackVictorSettings",
diff --git a/packages/overlays/IconPackVictorSystemUIOverlay/Android.bp b/packages/overlays/IconPackVictorSystemUIOverlay/Android.bp
index b8a9e77..2deb6cd 100644
--- a/packages/overlays/IconPackVictorSystemUIOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorSystemUIOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackVictorSystemUIOverlay",
theme: "IconPackVictorSystemUI",
diff --git a/packages/overlays/IconPackVictorThemePickerOverlay/Android.bp b/packages/overlays/IconPackVictorThemePickerOverlay/Android.bp
index 6f0144e..a18ebb3 100644
--- a/packages/overlays/IconPackVictorThemePickerOverlay/Android.bp
+++ b/packages/overlays/IconPackVictorThemePickerOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconPackVictorThemePickerOverlay",
theme: "IconPackVictorThemePicker",
diff --git a/packages/overlays/IconShapeHeartOverlay/Android.bp b/packages/overlays/IconShapeHeartOverlay/Android.bp
index ec55712..1da8f4f 100644
--- a/packages/overlays/IconShapeHeartOverlay/Android.bp
+++ b/packages/overlays/IconShapeHeartOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconShapeHeartOverlay",
theme: "IconShapeHeart",
diff --git a/packages/overlays/IconShapePebbleOverlay/Android.bp b/packages/overlays/IconShapePebbleOverlay/Android.bp
index 7dc4fde..fa2a5bb 100644
--- a/packages/overlays/IconShapePebbleOverlay/Android.bp
+++ b/packages/overlays/IconShapePebbleOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconShapePebbleOverlay",
theme: "IconShapePebble",
diff --git a/packages/overlays/IconShapeRoundedRectOverlay/Android.bp b/packages/overlays/IconShapeRoundedRectOverlay/Android.bp
index b8b8531..5052d08f 100644
--- a/packages/overlays/IconShapeRoundedRectOverlay/Android.bp
+++ b/packages/overlays/IconShapeRoundedRectOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconShapeRoundedRectOverlay",
theme: "IconShapeRoundedRect",
diff --git a/packages/overlays/IconShapeSquareOverlay/Android.bp b/packages/overlays/IconShapeSquareOverlay/Android.bp
index fdeffee..1176abd 100644
--- a/packages/overlays/IconShapeSquareOverlay/Android.bp
+++ b/packages/overlays/IconShapeSquareOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconShapeSquareOverlay",
theme: "IconShapeSquare",
diff --git a/packages/overlays/IconShapeSquircleOverlay/Android.bp b/packages/overlays/IconShapeSquircleOverlay/Android.bp
index 468f0f7..8c219f3 100644
--- a/packages/overlays/IconShapeSquircleOverlay/Android.bp
+++ b/packages/overlays/IconShapeSquircleOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconShapeSquircleOverlay",
theme: "IconShapeSquircle",
diff --git a/packages/overlays/IconShapeTaperedRectOverlay/Android.bp b/packages/overlays/IconShapeTaperedRectOverlay/Android.bp
index 1e48cd1..78855e8 100644
--- a/packages/overlays/IconShapeTaperedRectOverlay/Android.bp
+++ b/packages/overlays/IconShapeTaperedRectOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconShapeTaperedRectOverlay",
theme: "IconShapeTaperedRect",
diff --git a/packages/overlays/IconShapeTeardropOverlay/Android.bp b/packages/overlays/IconShapeTeardropOverlay/Android.bp
index 017d58ec..dd36f4f 100644
--- a/packages/overlays/IconShapeTeardropOverlay/Android.bp
+++ b/packages/overlays/IconShapeTeardropOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconShapeTeardropOverlay",
theme: "IconShapeTeardrop",
diff --git a/packages/overlays/IconShapeVesselOverlay/Android.bp b/packages/overlays/IconShapeVesselOverlay/Android.bp
index ba3b309..2e7f8bc 100644
--- a/packages/overlays/IconShapeVesselOverlay/Android.bp
+++ b/packages/overlays/IconShapeVesselOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "IconShapeVesselOverlay",
theme: "IconShapeVessel",
diff --git a/packages/overlays/NavigationBarMode2ButtonOverlay/Android.bp b/packages/overlays/NavigationBarMode2ButtonOverlay/Android.bp
index e4fcce1..35f671ba 100644
--- a/packages/overlays/NavigationBarMode2ButtonOverlay/Android.bp
+++ b/packages/overlays/NavigationBarMode2ButtonOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "NavigationBarMode2ButtonOverlay",
theme: "NavigationBarMode2Button",
diff --git a/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp b/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp
index 9b6c998..fe9cc81 100644
--- a/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp
+++ b/packages/overlays/NavigationBarMode3ButtonOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "NavigationBarMode3ButtonOverlay",
theme: "NavigationBarMode3Button",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlay/Android.bp
index ba29045..791f420 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/Android.bp
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "NavigationBarModeGesturalOverlay",
theme: "NavigationBarModeGestural",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp
index 0c688a9..28f9f33 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "NavigationBarModeGesturalOverlayExtraWideBack",
theme: "NavigationBarModeGesturalExtraWideBack",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp
index 85d514f..f8a5603 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "NavigationBarModeGesturalOverlayNarrowBack",
theme: "NavigationBarModeGesturalNarrowBack",
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp
index 84be626..60ee6d5 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "NavigationBarModeGesturalOverlayWideBack",
theme: "NavigationBarModeGesturalWideBack",
diff --git a/packages/overlays/OneHandedModeGesturalOverlay/Android.bp b/packages/overlays/OneHandedModeGesturalOverlay/Android.bp
index 9c9d0ef..468069d 100644
--- a/packages/overlays/OneHandedModeGesturalOverlay/Android.bp
+++ b/packages/overlays/OneHandedModeGesturalOverlay/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
runtime_resource_overlay {
name: "OneHandedModeGesturalOverlay",
theme: "OneHandedModeGestural",
diff --git a/packages/services/CameraExtensionsProxy/Android.bp b/packages/services/CameraExtensionsProxy/Android.bp
index e2e4af2..ea0703e 100644
--- a/packages/services/CameraExtensionsProxy/Android.bp
+++ b/packages/services/CameraExtensionsProxy/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_app {
name: "CameraExtensionsProxy",
srcs: ["src/**/*.java"],
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ea1473e..c63c2e1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -777,6 +777,10 @@
// performs the current profile parent resolution.
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
+ if (Binder.getCallingPid() == OWN_PROCESS_ID) {
+ return new ArrayList<>(getUserStateLocked(resolvedUserId).mInstalledServices);
+ }
return getUserStateLocked(resolvedUserId).mInstalledServices;
}
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 809304b..7518c7a 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2673,7 +2673,7 @@
AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
info.widgetFeatures = sa.getInt(
com.android.internal.R.styleable.AppWidgetProviderInfo_widgetFeatures, 0);
- info.descriptionResource = sa.getResourceId(
+ info.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AppWidgetProviderInfo_description,
Resources.ID_NULL);
sa.recycle();
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 6c30999..38275f7 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1245,10 +1245,9 @@
@Override
public IRestoreSession beginRestoreSessionForUser(
- int userId, String packageName, String transportID,
- @OperationType int operationType) throws RemoteException {
+ int userId, String packageName, String transportID) throws RemoteException {
return isUserReadyForBackup(userId)
- ? beginRestoreSession(userId, packageName, transportID, operationType) : null;
+ ? beginRestoreSession(userId, packageName, transportID) : null;
}
/**
@@ -1257,15 +1256,13 @@
*/
@Nullable
public IRestoreSession beginRestoreSession(
- @UserIdInt int userId, String packageName, String transportName,
- @OperationType int operationType) {
+ @UserIdInt int userId, String packageName, String transportName) {
UserBackupManagerService userBackupManagerService =
getServiceForUserIfCallerHasPermission(userId, "beginRestoreSession()");
return userBackupManagerService == null
? null
- : userBackupManagerService.beginRestoreSession(packageName, transportName,
- operationType);
+ : userBackupManagerService.beginRestoreSession(packageName, transportName);
}
@Override
@@ -1350,15 +1347,15 @@
if (!isUserReadyForBackup(userId)) {
return BackupManager.ERROR_BACKUP_NOT_ALLOWED;
}
- return requestBackup(userId, packages, observer, monitor, flags, OperationType.BACKUP);
+ return requestBackup(userId, packages, observer, monitor, flags);
}
@Override
public int requestBackup(String[] packages, IBackupObserver observer,
- IBackupManagerMonitor monitor, int flags, @OperationType int operationType)
+ IBackupManagerMonitor monitor, int flags)
throws RemoteException {
return requestBackup(binderGetCallingUserId(), packages,
- observer, monitor, flags, operationType);
+ observer, monitor, flags);
}
/**
@@ -1370,15 +1367,13 @@
String[] packages,
IBackupObserver observer,
IBackupManagerMonitor monitor,
- int flags,
- @OperationType int operationType) {
+ int flags) {
UserBackupManagerService userBackupManagerService =
getServiceForUserIfCallerHasPermission(userId, "requestBackup()");
return userBackupManagerService == null
? BackupManager.ERROR_BACKUP_NOT_ALLOWED
- : userBackupManagerService.requestBackup(packages, observer, monitor, flags,
- operationType);
+ : userBackupManagerService.requestBackup(packages, observer, monitor, flags);
}
@Override
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 136cd22f..9ee0159 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -96,6 +96,7 @@
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
+import android.util.FeatureFlagUtils;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -127,6 +128,7 @@
import com.android.server.backup.restore.ActiveRestoreSession;
import com.android.server.backup.restore.PerformUnifiedRestoreTask;
import com.android.server.backup.transport.TransportClient;
+import com.android.server.backup.transport.TransportNotAvailableException;
import com.android.server.backup.transport.TransportNotRegisteredException;
import com.android.server.backup.utils.BackupEligibilityRules;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
@@ -1860,19 +1862,10 @@
/**
* Requests a backup for the inputted {@code packages} with a specified {@link
- * IBackupManagerMonitor}.
- */
- public int requestBackup(String[] packages, IBackupObserver observer,
- IBackupManagerMonitor monitor, int flags) {
- return requestBackup(packages, observer, monitor, flags, OperationType.BACKUP);
- }
-
- /**
- * Requests a backup for the inputted {@code packages} with a specified {@link
* IBackupManagerMonitor} and {@link OperationType}.
*/
public int requestBackup(String[] packages, IBackupObserver observer,
- IBackupManagerMonitor monitor, int flags, @OperationType int operationType) {
+ IBackupManagerMonitor monitor, int flags) {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup");
if (packages == null || packages.length < 1) {
@@ -1903,13 +1896,16 @@
final TransportClient transportClient;
final String transportDirName;
+ int operationType;
try {
transportDirName =
mTransportManager.getTransportDirName(
mTransportManager.getCurrentTransportName());
transportClient =
mTransportManager.getCurrentTransportClientOrThrow("BMS.requestBackup()");
- } catch (TransportNotRegisteredException e) {
+ operationType = getOperationTypeFromTransport(transportClient);
+ } catch (TransportNotRegisteredException | TransportNotAvailableException
+ | RemoteException e) {
BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
@@ -4024,15 +4020,13 @@
}
/** Hand off a restore session. */
- public IRestoreSession beginRestoreSession(String packageName, String transport,
- @OperationType int operationType) {
+ public IRestoreSession beginRestoreSession(String packageName, String transport) {
if (DEBUG) {
Slog.v(
TAG,
addUserIdToLogMessage(
mUserId,
- "beginRestoreSession: pkg=" + packageName + " transport=" + transport
- + "operationType=" + operationType));
+ "beginRestoreSession: pkg=" + packageName + " transport=" + transport));
}
boolean needPermission = true;
@@ -4073,6 +4067,17 @@
}
}
+ int operationType;
+ try {
+ operationType = getOperationTypeFromTransport(
+ mTransportManager.getTransportClientOrThrow(transport, /* caller */
+ "BMS.beginRestoreSession"));
+ } catch (TransportNotAvailableException | TransportNotRegisteredException
+ | RemoteException e) {
+ Slog.w(TAG, "Failed to get operation type from transport: " + e);
+ return null;
+ }
+
synchronized (this) {
if (mActiveRestoreSession != null) {
Slog.i(
@@ -4356,6 +4361,34 @@
}
}
+ @VisibleForTesting
+ @OperationType int getOperationTypeFromTransport(TransportClient transportClient)
+ throws TransportNotAvailableException, RemoteException {
+ if (!shouldUseNewBackupEligibilityRules()) {
+ // Return the default to stick to the legacy behaviour.
+ return OperationType.BACKUP;
+ }
+
+ long oldCallingId = Binder.clearCallingIdentity();
+ try {
+ IBackupTransport transport = transportClient.connectOrThrow(
+ /* caller */ "BMS.getOperationTypeFromTransport");
+ if ((transport.getTransportFlags() & BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
+ return OperationType.MIGRATION;
+ } else {
+ return OperationType.BACKUP;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(oldCallingId);
+ }
+ }
+
+ @VisibleForTesting
+ boolean shouldUseNewBackupEligibilityRules() {
+ return FeatureFlagUtils.isEnabled(mContext,
+ FeatureFlagUtils.SETTINGS_USE_NEW_BACKUP_ELIGIBILITY_RULES);
+ }
+
private static String addUserIdToLogMessage(int userId, String message) {
return "[UserID:" + userId + "] " + message;
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 76c8d30..21cae45 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -142,18 +142,13 @@
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
-//TODO onStop schedule unbind in 5 seconds
-//TODO make sure APIs are only callable from currently focused app
-//TODO schedule stopScan on activity destroy(except if configuration change)
-//TODO on associate called again after configuration change -> replace old callback with new
-//TODO avoid leaking calling activity in IFindDeviceCallback (see PrintManager#print for example)
/** @hide */
@SuppressLint("LongLogTag")
public class CompanionDeviceManagerService extends SystemService implements Binder.DeathRecipient {
private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
- ".DeviceDiscoveryService");
+ ".CompanionDeviceDiscoveryService");
private static final long DEVICE_DISAPPEARED_TIMEOUT_MS = 10 * 1000;
private static final long DEVICE_DISAPPEARED_UNBIND_TIMEOUT_MS = 10 * 60 * 1000;
@@ -747,6 +742,15 @@
}
}
}
+
+ if (association.isNotifyOnDeviceNearby()) {
+ ServiceConnector<ICompanionDeviceService> serviceConnector =
+ mDeviceListenerServiceConnectors.forUser(association.getUserId())
+ .get(association.getPackageName());
+ if (serviceConnector != null) {
+ serviceConnector.unbind();
+ }
+ }
}
private void updateSpecialAccessPermissionForAssociatedPackage(Association association) {
@@ -1422,7 +1426,9 @@
}
@Override
- public void onDeviceDisconnected(BluetoothDevice device) {
+ public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {
+ Slog.d(LOG_TAG, device.getAddress() + " disconnected w/ reason: (" + reason + ") "
+ + BluetoothAdapter.BluetoothConnectionCallback.disconnectReasonText(reason));
CompanionDeviceManagerService.this.onDeviceDisconnected(device.getAddress());
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d26a7b1..f4138d1 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -197,6 +197,7 @@
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
+import com.android.net.module.util.PermissionUtils;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.DataConnectionStats;
@@ -1511,7 +1512,7 @@
@Override
public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
return getActiveNetworkForUidInternal(uid, ignoreBlocked);
}
@@ -1534,7 +1535,7 @@
@Override
public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
final NetworkState state = getUnfilteredActiveNetworkState(uid);
filterNetworkStateForUid(state, uid, ignoreBlocked);
return state.networkInfo;
@@ -1878,7 +1879,7 @@
@Override
public NetworkState[] getAllNetworkState() {
// This contains IMSI details, so make sure the caller is privileged.
- NetworkStack.checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
final ArrayList<NetworkState> result = new ArrayList<>();
for (Network network : getAllNetworks()) {
@@ -2302,7 +2303,7 @@
// Public because it's used by mLockdownTracker.
public void sendConnectedBroadcast(NetworkInfo info) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
sendGeneralBroadcast(info, CONNECTIVITY_ACTION);
}
@@ -4685,7 +4686,7 @@
@Override
public void setGlobalProxy(final ProxyInfo proxyProperties) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
mProxyTracker.setGlobalProxy(proxyProperties);
}
@@ -4887,7 +4888,7 @@
@Override
public void setRequireVpnForUids(boolean requireVpn, UidRange[] ranges) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_REQUIRE_VPN_FOR_UIDS,
encodeBool(requireVpn), 0 /* arg2 */, ranges));
}
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 88ce220..e29e894 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -28,6 +28,7 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.image.IDynamicSystemService;
+import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.util.Slog;
@@ -40,6 +41,7 @@
*/
public class DynamicSystemService extends IDynamicSystemService.Stub {
private static final String TAG = "DynamicSystemService";
+ private static final long MINIMUM_SD_MB = (30L << 10);
private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
private static final String PATH_DEFAULT = "/data/gsi/";
private Context mContext;
@@ -95,6 +97,13 @@
if (!volume.isMountedWritable()) {
continue;
}
+ DiskInfo disk = volume.getDisk();
+ long mega = disk.size >> 20;
+ Slog.i(TAG, volume.getPath() + ": " + mega + " MB");
+ if (mega < MINIMUM_SD_MB) {
+ Slog.i(TAG, volume.getPath() + ": insufficient storage");
+ continue;
+ }
File sd_internal = volume.getInternalPathForUser(userId);
if (sd_internal != null) {
path = new File(sd_internal, dsuSlot).getPath();
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index 84e429d..f2782f6 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -25,9 +25,9 @@
import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.hardware.SensorPrivacyManager.EXTRA_SENSOR;
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
+import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE;
import static android.os.UserHandle.USER_SYSTEM;
-import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA;
-import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE;
import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
import android.annotation.NonNull;
@@ -406,12 +406,12 @@
*/
@Override
public void setSensorPrivacy(boolean enable) {
+ enforceManageSensorPrivacyPermission();
// Keep the state consistent between all users to make it a single global state
forAllUsers(userId -> setSensorPrivacy(userId, enable));
}
private void setSensorPrivacy(@UserIdInt int userId, boolean enable) {
- enforceSensorPrivacyPermission();
synchronized (mLock) {
mEnabled.put(userId, enable);
persistSensorPrivacyStateLocked();
@@ -421,7 +421,7 @@
@Override
public void setIndividualSensorPrivacy(@UserIdInt int userId, int sensor, boolean enable) {
- enforceSensorPrivacyPermission();
+ enforceManageSensorPrivacyPermission();
synchronized (mLock) {
SparseBooleanArray userIndividualEnabled = mIndividualEnabled.get(userId,
new SparseBooleanArray());
@@ -448,6 +448,7 @@
@Override
public void setIndividualSensorPrivacyForProfileGroup(@UserIdInt int userId, int sensor,
boolean enable) {
+ enforceManageSensorPrivacyPermission();
int parentId = mUserManagerInternal.getProfileParentId(userId);
forAllUsers(userId2 -> {
if (parentId == mUserManagerInternal.getProfileParentId(userId2)) {
@@ -460,21 +461,35 @@
* Enforces the caller contains the necessary permission to change the state of sensor
* privacy.
*/
- private void enforceSensorPrivacyPermission() {
- if (mContext.checkCallingOrSelfPermission(
- MANAGE_SENSOR_PRIVACY) == PERMISSION_GRANTED) {
- return;
- }
- throw new SecurityException(
+ private void enforceManageSensorPrivacyPermission() {
+ enforcePermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY,
"Changing sensor privacy requires the following permission: "
+ MANAGE_SENSOR_PRIVACY);
}
/**
+ * Enforces the caller contains the necessary permission to observe changes to the sate of
+ * sensor privacy.
+ */
+ private void enforceObserveSensorPrivacyPermission() {
+ enforcePermission(android.Manifest.permission.OBSERVE_SENSOR_PRIVACY,
+ "Observing sensor privacy changes requires the following permission: "
+ + android.Manifest.permission.OBSERVE_SENSOR_PRIVACY);
+ }
+
+ private void enforcePermission(String permission, String message) {
+ if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
+ return;
+ }
+ throw new SecurityException(message);
+ }
+
+ /**
* Returns whether sensor privacy is enabled.
*/
@Override
public boolean isSensorPrivacyEnabled() {
+ enforceObserveSensorPrivacyPermission();
return isSensorPrivacyEnabled(USER_SYSTEM);
}
@@ -486,6 +501,7 @@
@Override
public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) {
+ enforceObserveSensorPrivacyPermission();
synchronized (mLock) {
SparseBooleanArray states = mIndividualEnabled.get(userId);
if (states == null) {
@@ -703,6 +719,7 @@
*/
@Override
public void addSensorPrivacyListener(ISensorPrivacyListener listener) {
+ enforceObserveSensorPrivacyPermission();
if (listener == null) {
throw new NullPointerException("listener cannot be null");
}
@@ -715,6 +732,7 @@
@Override
public void addIndividualSensorPrivacyListener(int userId, int sensor,
ISensorPrivacyListener listener) {
+ enforceObserveSensorPrivacyPermission();
if (listener == null) {
throw new NullPointerException("listener cannot be null");
}
@@ -726,6 +744,7 @@
*/
@Override
public void removeSensorPrivacyListener(ISensorPrivacyListener listener) {
+ enforceObserveSensorPrivacyPermission();
if (listener == null) {
throw new NullPointerException("listener cannot be null");
}
@@ -735,6 +754,7 @@
@Override
public void suppressIndividualSensorPrivacyReminders(int userId, String packageName,
IBinder token, boolean suppress) {
+ enforceManageSensorPrivacyPermission();
Objects.requireNonNull(packageName);
Objects.requireNonNull(token);
@@ -886,13 +906,13 @@
}
/**
- * Convert a string into a {@link SensorPrivacyManager.IndividualSensor id}.
+ * Convert a string into a {@link SensorPrivacyManager.Sensors.Sensor id}.
*
* @param sensor The name to convert
*
* @return The id corresponding to the name
*/
- private @SensorPrivacyManager.IndividualSensor int sensorStrToId(@Nullable String sensor) {
+ private @SensorPrivacyManager.Sensors.Sensor int sensorStrToId(@Nullable String sensor) {
if (sensor == null) {
return UNKNOWN;
}
@@ -950,7 +970,7 @@
return -1;
}
- enforceSensorPrivacyPermission();
+ enforceManageSensorPrivacyPermission();
synchronized (mLock) {
SparseBooleanArray individualEnabled =
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index c2d8fa2..8a2894c 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -45,14 +45,18 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.annotations.Immutable;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
@@ -87,26 +91,30 @@
/** Function to run on binder interface when first bound. */
public interface OnBindRunner {
/** Called to run client code with the binder. */
- void run(IBinder binder, ComponentName service) throws RemoteException;
+ void run(IBinder binder, BoundService service) throws RemoteException;
}
/**
* Information on the service ServiceWatcher has selected as the best option for binding.
*/
- private static final class ServiceInfo implements Comparable<ServiceInfo> {
+ @Immutable
+ public static final class BoundService implements Comparable<BoundService> {
- public static final ServiceInfo NONE = new ServiceInfo(Integer.MIN_VALUE, null,
- UserHandle.USER_NULL, false);
+ public static final BoundService NONE = new BoundService(Integer.MIN_VALUE, null,
+ false, null, -1);
public final int version;
- @Nullable public final ComponentName component;
- @UserIdInt public final int userId;
+ @Nullable
+ public final ComponentName component;
public final boolean serviceIsMultiuser;
+ public final int uid;
+ @Nullable
+ public final Bundle metadata;
- ServiceInfo(ResolveInfo resolveInfo, int currentUserId) {
+ BoundService(ResolveInfo resolveInfo) {
Preconditions.checkArgument(resolveInfo.serviceInfo.getComponentName() != null);
- Bundle metadata = resolveInfo.serviceInfo.metaData;
+ metadata = resolveInfo.serviceInfo.metaData;
if (metadata != null) {
version = metadata.getInt(EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
serviceIsMultiuser = metadata.getBoolean(EXTRA_SERVICE_IS_MULTIUSER, false);
@@ -116,16 +124,17 @@
}
component = resolveInfo.serviceInfo.getComponentName();
- userId = serviceIsMultiuser ? UserHandle.USER_SYSTEM : currentUserId;
+ uid = resolveInfo.serviceInfo.applicationInfo.uid;
}
- private ServiceInfo(int version, @Nullable ComponentName component, int userId,
- boolean serviceIsMultiuser) {
+ private BoundService(int version, @Nullable ComponentName component,
+ boolean serviceIsMultiuser, @Nullable Bundle metadata, int uid) {
Preconditions.checkArgument(component != null || version == Integer.MIN_VALUE);
this.version = version;
this.component = component;
- this.userId = userId;
this.serviceIsMultiuser = serviceIsMultiuser;
+ this.metadata = metadata;
+ this.uid = uid;
}
public @Nullable String getPackageName() {
@@ -137,21 +146,21 @@
if (this == o) {
return true;
}
- if (!(o instanceof ServiceInfo)) {
+ if (!(o instanceof BoundService)) {
return false;
}
- ServiceInfo that = (ServiceInfo) o;
- return version == that.version && userId == that.userId
+ BoundService that = (BoundService) o;
+ return version == that.version && uid == that.uid
&& Objects.equals(component, that.component);
}
@Override
public int hashCode() {
- return Objects.hash(version, component, userId);
+ return Objects.hash(version, component, uid);
}
@Override
- public int compareTo(ServiceInfo that) {
+ public int compareTo(BoundService that) {
// ServiceInfos with higher version numbers always win (having a version number >
// MIN_VALUE implies having a non-null component). if version numbers are equal, a
// non-null component wins over a null component. if the version numbers are equal and
@@ -164,10 +173,11 @@
} else if (component != null && that.component == null) {
ret = 1;
} else {
- if (userId != UserHandle.USER_SYSTEM && that.userId == UserHandle.USER_SYSTEM) {
+ if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM
+ && UserHandle.getUserId(that.uid) == UserHandle.USER_SYSTEM) {
ret = -1;
- } else if (userId == UserHandle.USER_SYSTEM
- && that.userId != UserHandle.USER_SYSTEM) {
+ } else if (UserHandle.getUserId(uid) == UserHandle.USER_SYSTEM
+ && UserHandle.getUserId(that.uid) != UserHandle.USER_SYSTEM) {
ret = 1;
}
}
@@ -180,7 +190,8 @@
if (component == null) {
return "none";
} else {
- return component.toShortString() + "@" + version + "[u" + userId + "]";
+ return component.toShortString() + "@" + version + "[u"
+ + UserHandle.getUserId(uid) + "]";
}
}
}
@@ -227,17 +238,23 @@
}
};
- @Nullable private final OnBindRunner mOnBind;
- @Nullable private final Runnable mOnUnbind;
+ // read/write from handler thread only
+ private final Map<ComponentName, BoundService> mPendingBinds = new ArrayMap<>();
- // write from caller thread only, read anywhere
- private volatile boolean mRegistered;
+ @Nullable
+ private final OnBindRunner mOnBind;
+
+ @Nullable
+ private final Runnable mOnUnbind;
+
+ // read/write from handler thread only
+ private boolean mRegistered;
// read/write from handler thread only
private int mCurrentUserId;
// write from handler thread only, read anywhere
- private volatile ServiceInfo mTargetService;
+ private volatile BoundService mTargetService;
private volatile IBinder mBinder;
public ServiceWatcher(Context context, String action,
@@ -274,7 +291,7 @@
mCurrentUserId = UserHandle.USER_NULL;
- mTargetService = ServiceInfo.NONE;
+ mTargetService = BoundService.NONE;
mBinder = null;
}
@@ -299,6 +316,11 @@
* Starts the process of determining the best matching service and maintaining a binding to it.
*/
public void register() {
+ mHandler.sendMessage(PooledLambda.obtainMessage(ServiceWatcher::registerInternal,
+ ServiceWatcher.this));
+ }
+
+ private void registerInternal() {
Preconditions.checkState(!mRegistered);
mPackageMonitor.register(mContext, UserHandle.ALL, true, mHandler);
@@ -309,6 +331,8 @@
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, intentFilter, null,
mHandler);
+ // TODO: This makes the behavior of the class unpredictable as the caller needs
+ // to know the internal impl detail that calling register would pick the current user.
mCurrentUserId = ActivityManager.getCurrentUser();
mRegistered = true;
@@ -320,6 +344,11 @@
* Stops the process of determining the best matching service and releases any binding.
*/
public void unregister() {
+ mHandler.sendMessage(PooledLambda.obtainMessage(ServiceWatcher::unregisterInternal,
+ ServiceWatcher.this));
+ }
+
+ private void unregisterInternal() {
Preconditions.checkState(mRegistered);
mRegistered = false;
@@ -333,7 +362,7 @@
private void onBestServiceChanged(boolean forceRebind) {
Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
- ServiceInfo bestServiceInfo = ServiceInfo.NONE;
+ BoundService bestServiceInfo = BoundService.NONE;
if (mRegistered) {
List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentServicesAsUser(
@@ -344,7 +373,7 @@
if (!mServiceCheckPredicate.test(resolveInfo)) {
continue;
}
- ServiceInfo serviceInfo = new ServiceInfo(resolveInfo, mCurrentUserId);
+ BoundService serviceInfo = new BoundService(resolveInfo);
if (serviceInfo.compareTo(bestServiceInfo) > 0) {
bestServiceInfo = serviceInfo;
}
@@ -356,21 +385,22 @@
}
}
- private void rebind(ServiceInfo newServiceInfo) {
+ private void rebind(BoundService newServiceInfo) {
Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
- if (!mTargetService.equals(ServiceInfo.NONE)) {
+ if (!mTargetService.equals(BoundService.NONE)) {
if (D) {
Log.d(TAG, "[" + mIntent.getAction() + "] unbinding from " + mTargetService);
}
mContext.unbindService(this);
onServiceDisconnected(mTargetService.component);
- mTargetService = ServiceInfo.NONE;
+ mPendingBinds.remove(mTargetService.component);
+ mTargetService = BoundService.NONE;
}
mTargetService = newServiceInfo;
- if (mTargetService.equals(ServiceInfo.NONE)) {
+ if (mTargetService.equals(BoundService.NONE)) {
return;
}
@@ -381,10 +411,12 @@
Intent bindIntent = new Intent(mIntent).setComponent(mTargetService.component);
if (!mContext.bindServiceAsUser(bindIntent, this,
BIND_AUTO_CREATE | BIND_NOT_FOREGROUND | BIND_NOT_VISIBLE,
- mHandler, UserHandle.of(mTargetService.userId))) {
- mTargetService = ServiceInfo.NONE;
+ mHandler, UserHandle.of(UserHandle.getUserId(mTargetService.uid)))) {
+ mTargetService = BoundService.NONE;
Log.e(TAG, getLogPrefix() + " unexpected bind failure - retrying later");
mHandler.postDelayed(() -> onBestServiceChanged(false), RETRY_DELAY_MS);
+ } else {
+ mPendingBinds.put(mTargetService.component, mTargetService);
}
}
@@ -397,10 +429,15 @@
Log.d(TAG, getLogPrefix() + " connected to " + component.toShortString());
}
+ final BoundService boundService = mPendingBinds.remove(component);
+ if (boundService == null) {
+ return;
+ }
+
mBinder = binder;
if (mOnBind != null) {
try {
- mOnBind.run(binder, component);
+ mOnBind.run(binder, boundService);
} catch (RuntimeException | RemoteException e) {
// binders may propagate some specific non-RemoteExceptions from the other side
// through the binder as well - we cannot allow those to crash the system server
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 2f98199..6be7f05 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -51,6 +51,7 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.AnrController;
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
@@ -938,14 +939,29 @@
if (transcodeEnabled) {
LocalServices.getService(ActivityManagerInternal.class)
- .registerAnrController((packageName, uid) -> {
- try {
- return mStorageSessionController.getAnrDelayMillis(packageName, uid);
- } catch (ExternalStorageServiceException e) {
- Log.e(TAG, "Failed to get ANR delay for " + packageName, e);
- return 0;
- }
- });
+ .registerAnrController(new ExternalStorageServiceAnrController());
+ }
+ }
+
+ // TODO(b/170486601): Check transcoding status based on events pushed from the MediaProvider
+ private class ExternalStorageServiceAnrController implements AnrController {
+ @Override
+ public long getAnrDelayMillis(String packageName, int uid) {
+ int delay = SystemProperties.getInt("sys.fuse.transcode_anr_delay", 0);
+ Log.d(TAG, "getAnrDelayMillis: " + packageName + ". Delaying for " + delay + "ms");
+ return delay;
+ }
+
+ @Override
+ public void onAnrDelayStarted(String packageName, int uid) {
+ Log.d(TAG, "onAnrDelayStarted: " + packageName);
+ }
+
+ @Override
+ public boolean onAnrDelayCompleted(String packageName, int uid) {
+ boolean show = SystemProperties.getBoolean("sys.fuse.transcode_anr_dialog_show", true);
+ Log.d(TAG, "onAnrDelayCompleted: " + packageName + ". Show: " + show);
+ return show;
}
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index b09b6ca..5a5f1a3 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -313,9 +313,9 @@
private List<PhysicalChannelConfig> mPhysicalChannelConfigs;
- private boolean mIsDataEnabled = false;
+ private boolean[] mIsDataEnabled;
- private int mDataEnabledReason;
+ private int[] mDataEnabledReason;
private Map<Integer, Long> mAllowedNetworkTypesList;
@@ -524,6 +524,8 @@
mOutgoingCallEmergencyNumber = copyOf(mOutgoingCallEmergencyNumber, mNumPhones);
mOutgoingSmsEmergencyNumber = copyOf(mOutgoingSmsEmergencyNumber, mNumPhones);
mTelephonyDisplayInfos = copyOf(mTelephonyDisplayInfos, mNumPhones);
+ mIsDataEnabled= copyOf(mIsDataEnabled, mNumPhones);
+ mDataEnabledReason = copyOf(mDataEnabledReason, mNumPhones);
// ds -> ss switch.
if (mNumPhones < oldNumPhones) {
@@ -565,6 +567,8 @@
mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
+ mIsDataEnabled[i] = false;
+ mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER;
mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
}
}
@@ -626,6 +630,8 @@
mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones];
mPhysicalChannelConfigs = new ArrayList<>();
mAllowedNetworkTypesList = new HashMap<>();
+ mIsDataEnabled = new boolean[numPhones];
+ mDataEnabledReason = new int[numPhones];
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
@@ -655,6 +661,8 @@
mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
+ mIsDataEnabled[i] = false;
+ mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER;
mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
}
@@ -1150,7 +1158,8 @@
if (events.contains(
PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) {
try {
- r.callback.onDataEnabledChanged(mIsDataEnabled, mDataEnabledReason);
+ r.callback.onDataEnabledChanged(
+ mIsDataEnabled[phoneId], mDataEnabledReason[phoneId]);
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -2370,30 +2379,36 @@
/**
* Notify that the data enabled has changed.
*
+ * @param phoneId the phone id.
+ * @param subId the subId.
* @param enabled True if data is enabled, otherwise disabled.
* @param reason Reason for data enabled/disabled. See {@code DATA_*} in
* {@link TelephonyManager}.
*/
- public void notifyDataEnabled(boolean enabled,
+ public void notifyDataEnabled(int phoneId, int subId, boolean enabled,
@TelephonyManager.DataEnabledReason int reason) {
if (!checkNotifyPermission("notifyDataEnabled()")) {
return;
}
if (VDBG) {
- log("notifyDataEnabled: enabled=" + enabled + " reason=" + reason);
+ log("notifyDataEnabled: PhoneId=" + phoneId + " subId=" + subId +
+ " enabled=" + enabled + " reason=" + reason);
}
- mIsDataEnabled = enabled;
- mDataEnabledReason = reason;
synchronized (mRecords) {
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) {
- try {
- r.callback.onDataEnabledChanged(enabled, reason);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
+ if (validatePhoneId(phoneId)) {
+ mIsDataEnabled[phoneId] = enabled;
+ mDataEnabledReason[phoneId] = reason;
+ for (Record r : mRecords) {
+ if (r.matchPhoneStateListenerEvent(
+ PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)
+ && idMatch(r.subId, subId, phoneId)) {
+ try {
+ r.callback.onDataEnabledChanged(enabled, reason);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
}
}
}
@@ -2481,6 +2496,8 @@
pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]);
pw.println("mBarringInfo=" + mBarringInfo.get(i));
pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]);
+ pw.println("mIsDataEnabled=" + mIsDataEnabled);
+ pw.println("mDataEnabledReason=" + mDataEnabledReason);
pw.decreaseIndent();
}
pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
@@ -2491,8 +2508,6 @@
pw.println("mDefaultPhoneId=" + mDefaultPhoneId);
pw.println("mDefaultSubId=" + mDefaultSubId);
pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs);
- pw.println("mIsDataEnabled=" + mIsDataEnabled);
- pw.println("mDataEnabledReason=" + mDataEnabledReason);
pw.decreaseIndent();
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 329ab99..8d5d3d9 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
+
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
@@ -837,7 +839,10 @@
// Notify all registered StatusCallbacks for this subGroup
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
if (isCallbackPermissioned(cbInfo)) {
- Binder.withCleanCallingIdentity(() -> cbInfo.mCallback.onEnteredSafeMode());
+ Binder.withCleanCallingIdentity(
+ () ->
+ cbInfo.mCallback.onVcnStatusChanged(
+ VCN_STATUS_CODE_SAFE_MODE));
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d03eea2..a36d913 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -142,6 +142,8 @@
import android.app.Activity;
import android.app.ActivityClient;
import android.app.ActivityManager;
+import android.app.ActivityManager.PendingIntentInfo;
+import android.app.ActivityManager.ProcessCapability;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManagerInternal;
import android.app.ActivityTaskManager.RootTaskInfo;
@@ -182,7 +184,6 @@
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
-import android.compat.Compatibility;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -306,8 +307,8 @@
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.SystemUserHomeActivity;
+import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
-import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.content.PackageHelper;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
@@ -1820,6 +1821,15 @@
ncl.start();
}
+ /**
+ * Sets a policy for handling app ops.
+ *
+ * @param appOpsPolicy The policy.
+ */
+ public void setAppOpsPolicy(@Nullable CheckOpsDelegate appOpsPolicy) {
+ mAppOpsService.setAppOpsPolicy(appOpsPolicy);
+ }
+
public IAppOpsService getAppOpsService() {
return mAppOpsService;
}
@@ -3779,10 +3789,11 @@
mi.getTotalUss(), mi.getTotalRss(), false,
ProcessStats.ADD_PSS_EXTERNAL_SLOW, duration);
proc.getPkgList().forEachPackageProcessStats(holder -> {
+ final ProcessState state = holder.state;
FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
proc.info.uid,
- holder.state.getName(),
- holder.state.getPackage(),
+ state != null ? state.getName() : proc.processName,
+ state != null ? state.getPackage() : proc.info.packageName,
mi.getTotalPss(),
mi.getTotalUss(),
mi.getTotalRss(),
@@ -4860,19 +4871,6 @@
}
@Override
- public String getPackageForIntentSender(IIntentSender pendingResult) {
- if (!(pendingResult instanceof PendingIntentRecord)) {
- return null;
- }
- try {
- PendingIntentRecord res = (PendingIntentRecord)pendingResult;
- return res.key.packageName;
- } catch (ClassCastException e) {
- }
- return null;
- }
-
- @Override
public void registerIntentSenderCancelListener(IIntentSender sender, IResultReceiver receiver) {
mPendingIntentController.registerIntentSenderCancelListener(sender, receiver);
}
@@ -4884,15 +4882,17 @@
}
@Override
- public int getUidForIntentSender(IIntentSender sender) {
+ public PendingIntentInfo getInfoForIntentSender(IIntentSender sender) {
if (sender instanceof PendingIntentRecord) {
- try {
- PendingIntentRecord res = (PendingIntentRecord)sender;
- return res.uid;
- } catch (ClassCastException e) {
- }
+ PendingIntentRecord res = (PendingIntentRecord) sender;
+ return new PendingIntentInfo(
+ res.key.packageName,
+ res.uid,
+ (res.key.flags & PendingIntent.FLAG_IMMUTABLE) != 0,
+ res.key.type);
+ } else {
+ throw new IllegalArgumentException();
}
- return -1;
}
@Override
@@ -4918,15 +4918,6 @@
}
@Override
- public boolean isIntentSenderImmutable(IIntentSender pendingResult) {
- if (pendingResult instanceof PendingIntentRecord) {
- final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
- return (res.key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
- }
- return false;
- }
-
- @Override
public boolean isIntentSenderAnActivity(IIntentSender pendingResult) {
if (!(pendingResult instanceof PendingIntentRecord)) {
return false;
@@ -4943,33 +4934,6 @@
}
@Override
- public boolean isIntentSenderAForegroundService(IIntentSender pendingResult) {
- if (pendingResult instanceof PendingIntentRecord) {
- final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
- return res.key.type == ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE;
- }
- return false;
- }
-
- @Override
- public boolean isIntentSenderAService(IIntentSender pendingResult) {
- if (pendingResult instanceof PendingIntentRecord) {
- final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
- return res.key.type == ActivityManager.INTENT_SENDER_SERVICE;
- }
- return false;
- }
-
- @Override
- public boolean isIntentSenderABroadcast(IIntentSender pendingResult) {
- if (pendingResult instanceof PendingIntentRecord) {
- final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
- return res.key.type == ActivityManager.INTENT_SENDER_BROADCAST;
- }
- return false;
- }
-
- @Override
public Intent getIntentForIntentSender(IIntentSender pendingResult) {
enforceCallingPermission(Manifest.permission.GET_INTENT_SENDER_INTENT,
"getIntentForIntentSender()");
@@ -6634,6 +6598,18 @@
}
@Override
+ public @ProcessCapability int getUidProcessCapabilities(int uid, String callingPackage) {
+ if (!hasUsageStatsPermission(callingPackage)) {
+ enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS,
+ "getUidProcessState");
+ }
+
+ synchronized (mProcLock) {
+ return mProcessList.getUidProcessCapabilityLOSP(uid);
+ }
+ }
+
+ @Override
public void registerUidObserver(IUidObserver observer, int which, int cutpoint,
String callingPackage) {
if (!hasUsageStatsPermission(callingPackage)) {
@@ -7249,6 +7225,9 @@
final long memoryGrowthThreshold =
Math.max(totalMemoryInKb / 100, MINIMUM_MEMORY_GROWTH_THRESHOLD);
mProcessList.forEachLruProcessesLOSP(false, proc -> {
+ if (proc.getThread() == null) {
+ return;
+ }
final ProcessProfileRecord pr = proc.mProfile;
final ProcessStateRecord state = proc.mState;
final int setProcState = state.getSetProcState();
@@ -10079,6 +10058,7 @@
ProcessList.PERSISTENT_SERVICE_ADJ, ProcessList.FOREGROUND_APP_ADJ,
ProcessList.VISIBLE_APP_ADJ,
ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_LOW_APP_ADJ,
+ ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ,
ProcessList.BACKUP_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.CACHED_APP_MIN_ADJ
@@ -10086,7 +10066,7 @@
static final String[] DUMP_MEM_OOM_LABEL = new String[] {
"Native",
"System", "Persistent", "Persistent Service", "Foreground",
- "Visible", "Perceptible", "Perceptible Low",
+ "Visible", "Perceptible", "Perceptible Low", "Perceptible Medium",
"Heavy Weight", "Backup",
"A Services", "Home",
"Previous", "B Services", "Cached"
@@ -10094,7 +10074,7 @@
static final String[] DUMP_MEM_OOM_COMPACT_LABEL = new String[] {
"native",
"sys", "pers", "persvc", "fore",
- "vis", "percept", "perceptl",
+ "vis", "percept", "perceptl", "perceptm",
"heavy", "backup",
"servicea", "home",
"prev", "serviceb", "cached"
@@ -13571,8 +13551,6 @@
if (disableHiddenApiChecks || disableTestApiChecks) {
enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
"disable hidden API checks");
-
- enableTestApiAccess(ai.packageName);
}
final long origId = Binder.clearCallingIdentity();
@@ -13746,25 +13724,6 @@
app.userId,
"finished inst");
}
-
- disableTestApiAccess(app.info.packageName);
- }
-
- private void enableTestApiAccess(String packageName) {
- if (mPlatformCompat != null) {
- Compatibility.ChangeConfig config = new Compatibility.ChangeConfig(
- Collections.singleton(166236554L /* VMRuntime.ALLOW_TEST_API_ACCESS */),
- Collections.emptySet());
- CompatibilityChangeConfig override = new CompatibilityChangeConfig(config);
- mPlatformCompat.setOverridesForTest(override, packageName);
- }
- }
-
- private void disableTestApiAccess(String packageName) {
- if (mPlatformCompat != null) {
- mPlatformCompat.clearOverrideForTest(166236554L /* VMRuntime.ALLOW_TEST_API_ACCESS */,
- packageName);
- }
}
public void finishInstrumentation(IApplicationThread target,
@@ -13973,7 +13932,7 @@
}
void noteUidProcessState(final int uid, final int state,
- final @ActivityManager.ProcessCapability int capability) {
+ final @ProcessCapability int capability) {
mBatteryStatsService.noteUidProcessState(uid, state);
mAppOpsService.updateUidProcState(uid, state, capability);
if (mTrackingAssociations) {
@@ -14024,6 +13983,9 @@
final long uptimeSince = curUptime - mLastPowerCheckUptime;
mLastPowerCheckUptime = curUptime;
mProcessList.forEachLruProcessesLOSP(false, app -> {
+ if (app.getThread() == null) {
+ return;
+ }
if (app.mState.getSetProcState() >= ActivityManager.PROCESS_STATE_HOME) {
int cpuLimit;
long checkDur = curUptime - app.mState.getWhenUnimportant();
@@ -14125,11 +14087,12 @@
mBatteryStatsService.reportExcessiveCpu(app.info.uid, app.processName,
uptimeSince, cputimeUsed);
app.getPkgList().forEachPackageProcessStats(holder -> {
+ final ProcessState state = holder.state;
FrameworkStatsLog.write(
FrameworkStatsLog.EXCESSIVE_CPU_USAGE_REPORTED,
app.info.uid,
processName,
- holder.state.getPackage(),
+ state != null ? state.getPackage() : app.info.packageName,
holder.appVersion);
});
return true;
diff --git a/services/core/java/com/android/server/am/AppErrorDialog.java b/services/core/java/com/android/server/am/AppErrorDialog.java
index 48222cb..a9e5571 100644
--- a/services/core/java/com/android/server/am/AppErrorDialog.java
+++ b/services/core/java/com/android/server/am/AppErrorDialog.java
@@ -18,10 +18,7 @@
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.Build;
import android.os.Bundle;
@@ -138,19 +135,6 @@
findViewById(com.android.internal.R.id.customPanel).setVisibility(View.VISIBLE);
}
- @Override
- public void onStart() {
- super.onStart();
- getContext().registerReceiver(mReceiver,
- new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- getContext().unregisterReceiver(mReceiver);
- }
-
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
setResult(msg.what);
@@ -204,15 +188,6 @@
}
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
- cancel();
- }
- }
- };
-
static class Data {
AppErrorResult result;
int taskId;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index e5a5cff..3602f44 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -29,6 +29,7 @@
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.AnrController;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.content.ActivityNotFoundException;
@@ -1058,7 +1059,26 @@
Settings.Secure.ANR_SHOW_BACKGROUND, 0,
mService.mUserController.getCurrentUserId()) != 0;
if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
- errState.getDialogController().showAnrDialogs(data);
+ AnrController anrController = errState.getDialogController().getAnrController();
+ if (anrController == null) {
+ errState.getDialogController().showAnrDialogs(data);
+ } else {
+ String packageName = proc.info.packageName;
+ int uid = proc.info.uid;
+ boolean showDialog = anrController.onAnrDelayCompleted(packageName, uid);
+
+ if (showDialog) {
+ Slog.d(TAG, "ANR delay completed. Showing ANR dialog for package: "
+ + packageName);
+ errState.getDialogController().showAnrDialogs(data);
+ } else {
+ Slog.d(TAG, "ANR delay completed. Cancelling ANR dialog for package: "
+ + packageName);
+ errState.setNotResponding(false);
+ errState.setNotRespondingReport(null);
+ errState.getDialogController().clearAnrDialogs();
+ }
+ }
} else {
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
AppNotRespondingDialog.CANT_SHOW);
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 77d2898..b233a2c 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -181,6 +181,11 @@
}
};
+ @Override
+ protected void closeDialog() {
+ mHandler.obtainMessage(FORCE_CLOSE).sendToTarget();
+ }
+
static class Data {
final ProcessRecord proc;
final ApplicationInfo aInfo;
diff --git a/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
index 3ce2471..262e795 100644
--- a/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
+++ b/services/core/java/com/android/server/am/AppWaitingForDebuggerDialog.java
@@ -61,6 +61,11 @@
public void onStop() {
}
+ @Override
+ protected void closeDialog() {
+ /* Do nothing */
+ }
+
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index aabb587..7b5f2cd 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -16,16 +16,19 @@
package com.android.server.am;
-import com.android.internal.R;
-
import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.Button;
+import com.android.internal.R;
+
public class BaseErrorDialog extends AlertDialog {
private static final int ENABLE_BUTTONS = 0;
private static final int DISABLE_BUTTONS = 1;
@@ -44,10 +47,19 @@
getWindow().setAttributes(attrs);
}
+ @Override
public void onStart() {
super.onStart();
mHandler.sendEmptyMessage(DISABLE_BUTTONS);
mHandler.sendMessageDelayed(mHandler.obtainMessage(ENABLE_BUTTONS), 1000);
+ getContext().registerReceiver(mReceiver,
+ new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ getContext().unregisterReceiver(mReceiver);
}
public boolean dispatchKeyEvent(KeyEvent event) {
@@ -84,4 +96,24 @@
}
}
};
+
+ /**
+ * Called when received ACTION_CLOSE_SYSTEM_DIALOGS.
+ */
+ protected void closeDialog() {
+ if (mCancelable) {
+ cancel();
+ } else {
+ dismiss();
+ }
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ closeDialog();
+ }
+ }
+ };
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index a34163c..c5f082a 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -536,18 +536,6 @@
}
/**
- * Enable or disable the freezer. When enable == false all frozen processes are unfrozen,
- * but aren't removed from the freezer. While in this state, processes can be added or removed
- * by using Process.setProcessFrozen(), but they wouldn't be actually frozen until the freezer
- * is enabled. If enable == true all processes in the freezer are frozen.
- *
- * @param enable Specify whether to enable (true) or disable (false) the freezer.
- *
- * @hide
- */
- private static native void enableFreezerInternal(boolean enable);
-
- /**
* Informs binder that a process is about to be frozen. If freezer is enabled on a process via
* this method, this method will synchronously dispatch all pending transactions to the
* specified pid. This method will not add significant latencies when unfreezing.
@@ -590,10 +578,6 @@
if (state == '1' || state == '0') {
supported = true;
- // This is a workaround after reverting the cgroup v2 uid/pid hierarchy due to
- // http://b/179006802.
- // TODO: remove once the uid/pid hierarchy is restored
- enableFreezerInternal(true);
} else {
Slog.e(TAG_AM, "unexpected value in cgroup.freeze");
}
diff --git a/services/core/java/com/android/server/am/ErrorDialogController.java b/services/core/java/com/android/server/am/ErrorDialogController.java
index ef135d5..f23d309 100644
--- a/services/core/java/com/android/server/am/ErrorDialogController.java
+++ b/services/core/java/com/android/server/am/ErrorDialogController.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import android.annotation.Nullable;
+import android.app.AnrController;
import android.app.Dialog;
import android.content.Context;
@@ -57,6 +59,13 @@
@GuardedBy("mProcLock")
private AppWaitingForDebuggerDialog mWaitDialog;
+ /**
+ * ANR dialog controller
+ */
+ @GuardedBy("mProcLock")
+ @Nullable
+ private AnrController mAnrController;
+
@GuardedBy("mProcLock")
boolean hasCrashDialogs() {
return mCrashDialogs != null;
@@ -118,6 +127,7 @@
}
forAllDialogs(mAnrDialogs, Dialog::dismiss);
mAnrDialogs = null;
+ mAnrController = null;
}
@GuardedBy("mProcLock")
@@ -220,6 +230,17 @@
});
}
+ @GuardedBy("mProcLock")
+ @Nullable
+ AnrController getAnrController() {
+ return mAnrController;
+ }
+
+ @GuardedBy("mProcLock")
+ void setAnrController(AnrController controller) {
+ mAnrController = controller;
+ }
+
/**
* Helper function to collect contexts from crashed app located displays.
*
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 87cba54..b956e30 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -21,6 +21,7 @@
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
@@ -1981,6 +1982,21 @@
capability |= cstate.getCurCapability();
}
+ // If an app has network capability by default
+ // (by having procstate <= BFGS), then the apps it binds to will get
+ // elevated to a high enough procstate anyway to get network unless they
+ // request otherwise, so don't propagate the network capability by default
+ // in this case unless they explicitly request it.
+ if ((cstate.getCurCapability() & PROCESS_CAPABILITY_NETWORK) != 0) {
+ if (clientProcState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
+ if ((cr.flags & Context.BIND_ALLOW_NETWORK_ACCESS) != 0) {
+ capability |= PROCESS_CAPABILITY_NETWORK;
+ }
+ } else {
+ capability |= PROCESS_CAPABILITY_NETWORK;
+ }
+ }
+
if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
// If the other app is cached for any reason, for purposes here
// we are going to consider it empty. The specific cached state
@@ -2048,6 +2064,10 @@
&& clientAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
&& adj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
newAdj = ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
+ } else if ((cr.flags & Context.BIND_ALMOST_PERCEPTIBLE) != 0
+ && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
+ && adj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) {
+ newAdj = ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
} else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
&& clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
&& adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -2117,13 +2137,13 @@
if (enabled) {
if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
// TOP process passes all capabilities to the service.
- capability |= PROCESS_CAPABILITY_ALL;
+ capability |= cstate.getCurCapability();
} else {
// TOP process passes no capability to the service.
}
} else {
// TOP process passes all capabilities to the service.
- capability |= PROCESS_CAPABILITY_ALL;
+ capability |= cstate.getCurCapability();
}
}
} else if ((cr.flags & Context.BIND_IMPORTANT_BACKGROUND) == 0) {
@@ -2448,20 +2468,20 @@
case PROCESS_STATE_TOP:
return PROCESS_CAPABILITY_ALL;
case PROCESS_STATE_BOUND_TOP:
- return PROCESS_CAPABILITY_NONE;
+ return PROCESS_CAPABILITY_NETWORK;
case PROCESS_STATE_FOREGROUND_SERVICE:
if (psr.hasForegroundServices()) {
// Capability from FGS are conditional depending on foreground service type in
// manifest file and the mAllowWhileInUsePermissionInFgs flag.
- return PROCESS_CAPABILITY_NONE;
+ return PROCESS_CAPABILITY_NETWORK;
} else {
// process has no FGS, the PROCESS_STATE_FOREGROUND_SERVICE is from client.
// the implicit capability could be removed in the future, client should use
// BIND_INCLUDE_CAPABILITY flag.
- return PROCESS_CAPABILITY_ALL_IMPLICIT;
+ return PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK;
}
case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
- return PROCESS_CAPABILITY_NONE;
+ return PROCESS_CAPABILITY_NETWORK;
default:
return PROCESS_CAPABILITY_NONE;
}
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 1653123..3258f8a 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -22,6 +22,7 @@
import static com.android.server.am.ProcessRecord.TAG;
import android.app.ActivityManager;
+import android.app.AnrController;
import android.app.ApplicationErrorReport;
import android.app.ApplicationExitInfo;
import android.content.ComponentName;
@@ -418,10 +419,16 @@
// Retrieve max ANR delay from AnrControllers without the mService lock since the
// controllers might in turn call into apps
- long anrDialogDelayMs = mService.mActivityTaskManager.getMaxAnrDelayMillis(aInfo);
- if (aInfo != null && aInfo.packageName != null && anrDialogDelayMs > 0) {
- Slog.i(TAG, "Delaying ANR dialog for " + aInfo.packageName + " for " + anrDialogDelayMs
- + "ms");
+ AnrController anrController = mService.mActivityTaskManager.getAnrController(aInfo);
+ long anrDialogDelayMs = 0;
+ if (anrController != null) {
+ String packageName = aInfo.packageName;
+ int uid = aInfo.uid;
+ anrDialogDelayMs = anrController.getAnrDelayMillis(packageName, uid);
+ // Might execute an async binder call to a system app to show an interim
+ // ANR progress UI
+ anrController.onAnrDelayStarted(packageName, uid);
+ Slog.i(TAG, "ANR delay of " + anrDialogDelayMs + "ms started for " + packageName);
}
synchronized (mService) {
@@ -440,6 +447,7 @@
// Set the app's notResponding state, and look up the errorReportReceiver
makeAppNotRespondingLSP(activityShortComponentName,
annotation != null ? "ANR " + annotation : "ANR", info.toString());
+ mDialogController.setAnrController(anrController);
}
// Notify package manager service to possibly update package state
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index cb07a06..38330fe 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityThread.PROC_START_SEQ_IDENT;
@@ -57,6 +58,7 @@
import android.annotation.NonNull;
import android.app.ActivityManager;
+import android.app.ActivityManager.ProcessCapability;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.AppProtoEnums;
@@ -228,6 +230,11 @@
// not so perceptible that it affects the user immediately if killed.
static final int PERCEPTIBLE_LOW_APP_ADJ = 250;
+ // This is a process hosting services that are not perceptible to the user but the
+ // client (system) binding to it requested to treat it as if it is perceptible and avoid killing
+ // it if possible.
+ static final int PERCEPTIBLE_MEDIUM_APP_ADJ = 225;
+
// This is a process only hosting components that are perceptible to the
// user, and we really want to avoid killing them, but they are not
// immediately visible. An example is background music playback.
@@ -1027,6 +1034,9 @@
} else if (setAdj >= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
return buildOomTag("prcl ", "prcl", null, setAdj,
ProcessList.PERCEPTIBLE_LOW_APP_ADJ, compact);
+ } else if (setAdj >= ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ) {
+ return buildOomTag("prcm ", "prcm", null, setAdj,
+ ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ, compact);
} else if (setAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
return buildOomTag("prcp ", "prcp", null, setAdj,
ProcessList.PERCEPTIBLE_APP_ADJ, compact);
@@ -4395,6 +4405,7 @@
printOomLevel(pw, "FOREGROUND_APP_ADJ", FOREGROUND_APP_ADJ);
printOomLevel(pw, "VISIBLE_APP_ADJ", VISIBLE_APP_ADJ);
printOomLevel(pw, "PERCEPTIBLE_APP_ADJ", PERCEPTIBLE_APP_ADJ);
+ printOomLevel(pw, "PERCEPTIBLE_MEDIUM_APP_ADJ", PERCEPTIBLE_MEDIUM_APP_ADJ);
printOomLevel(pw, "PERCEPTIBLE_LOW_APP_ADJ", PERCEPTIBLE_LOW_APP_ADJ);
printOomLevel(pw, "BACKUP_APP_ADJ", BACKUP_APP_ADJ);
printOomLevel(pw, "HEAVY_WEIGHT_APP_ADJ", HEAVY_WEIGHT_APP_ADJ);
@@ -4658,13 +4669,26 @@
}
}
- /** Returns the uid's process state or PROCESS_STATE_NONEXISTENT if not running */
+ /**
+ * Returns the uid's process state or {@link ActivityManager#PROCESS_STATE_NONEXISTENT}
+ * if not running
+ */
@GuardedBy(anyOf = {"mService", "mProcLock"})
int getUidProcStateLOSP(int uid) {
UidRecord uidRec = mActiveUids.get(uid);
return uidRec == null ? PROCESS_STATE_NONEXISTENT : uidRec.getCurProcState();
}
+ /**
+ * Returns the uid's process capability or {@link ActivityManager#PROCESS_CAPABILITY_NONE}
+ * if not running
+ */
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
+ @ProcessCapability int getUidProcessCapabilityLOSP(int uid) {
+ UidRecord uidRec = mActiveUids.get(uid);
+ return uidRec == null ? PROCESS_CAPABILITY_NONE : uidRec.getCurCapability();
+ }
+
/** Returns the UidRecord for the given uid, if it exists. */
@GuardedBy(anyOf = {"mService", "mProcLock"})
UidRecord getUidRecordLOSP(int uid) {
@@ -4749,8 +4773,9 @@
if (!UserHandle.isApp(uidRec.getUid()) || !uidRec.hasInternetPermission) {
continue;
}
- // If process state is not changed, then there's nothing to do.
- if (uidRec.getSetProcState() == uidRec.getCurProcState()) {
+ // If process state and capabilities are not changed, then there's nothing to do.
+ if (uidRec.getSetProcState() == uidRec.getCurProcState()
+ && uidRec.getSetCapability() == uidRec.getCurCapability()) {
continue;
}
final int blockState = getBlockStateForUid(uidRec);
diff --git a/services/core/java/com/android/server/am/StrictModeViolationDialog.java b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
index 4cc1fc1..9dddd65 100644
--- a/services/core/java/com/android/server/am/StrictModeViolationDialog.java
+++ b/services/core/java/com/android/server/am/StrictModeViolationDialog.java
@@ -82,6 +82,11 @@
DISMISS_TIMEOUT);
}
+ @Override
+ protected void closeDialog() {
+ mHandler.obtainMessage(ACTION_OK).sendToTarget();
+ }
+
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
synchronized (mService.mProcLock) {
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index e97f0b4..33bdac2 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -23,9 +23,12 @@
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
+import static com.android.server.apphibernation.AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.ActivityThread;
import android.app.IActivityManager;
import android.apphibernation.IAppHibernationService;
import android.content.BroadcastReceiver;
@@ -45,6 +48,8 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.Properties;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -93,6 +98,9 @@
private final HibernationStateDiskStore<GlobalLevelState> mGlobalLevelHibernationDiskStore;
private final Injector mInjector;
+ @VisibleForTesting
+ boolean mIsServiceEnabled;
+
/**
* Initializes the system service.
* <p>
@@ -139,6 +147,13 @@
initializeGlobalHibernationStates(states);
}
}
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ mIsServiceEnabled = isAppHibernationEnabled();
+ DeviceConfig.addOnPropertiesChangedListener(
+ NAMESPACE_APP_HIBERNATION,
+ ActivityThread.currentApplication().getMainExecutor(),
+ this::onDeviceConfigChanged);
+ }
}
/**
@@ -149,6 +164,10 @@
* @return true if package is hibernating for the user
*/
boolean isHibernatingForUser(String packageName, int userId) {
+ if (!checkHibernationEnabled("isHibernatingForUser")) {
+ return false;
+ }
+
userId = handleIncomingUser(userId, "isHibernating");
if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
Slog.e(TAG, "Attempt to get hibernation state of stopped or nonexistent user "
@@ -174,6 +193,9 @@
* @param packageName package to check
*/
boolean isHibernatingGlobally(String packageName) {
+ if (!checkHibernationEnabled("isHibernatingGlobally")) {
+ return false;
+ }
synchronized (mLock) {
GlobalLevelState state = mGlobalHibernationStates.get(packageName);
if (state == null) {
@@ -192,6 +214,9 @@
* @param isHibernating new hibernation state
*/
void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
+ if (!checkHibernationEnabled("setHibernatingForUser")) {
+ return;
+ }
userId = handleIncomingUser(userId, "setHibernating");
if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
Slog.w(TAG, "Attempt to set hibernation state for a stopped or nonexistent user "
@@ -229,6 +254,9 @@
* @param isHibernating new hibernation state
*/
void setHibernatingGlobally(String packageName, boolean isHibernating) {
+ if (!checkHibernationEnabled("setHibernatingGlobally")) {
+ return;
+ }
synchronized (mLock) {
GlobalLevelState state = mGlobalHibernationStates.get(packageName);
if (state == null) {
@@ -421,6 +449,9 @@
private void onPackageAdded(@NonNull String packageName, int userId) {
synchronized (mLock) {
+ if (!mUserStates.contains(userId)) {
+ return;
+ }
UserLevelState userState = new UserLevelState();
userState.packageName = packageName;
mUserStates.get(userId).put(packageName, userState);
@@ -434,6 +465,9 @@
private void onPackageRemoved(@NonNull String packageName, int userId) {
synchronized (mLock) {
+ if (!mUserStates.contains(userId)) {
+ return;
+ }
mUserStates.get(userId).remove(packageName);
}
}
@@ -444,6 +478,15 @@
}
}
+ private void onDeviceConfigChanged(Properties properties) {
+ for (String key : properties.getKeyset()) {
+ if (TextUtils.equals(KEY_APP_HIBERNATION_ENABLED, key)) {
+ mIsServiceEnabled = isAppHibernationEnabled();
+ break;
+ }
+ }
+ }
+
/**
* Private helper method to get the real user id and enforce permission checks.
*
@@ -461,6 +504,13 @@
}
}
+ private boolean checkHibernationEnabled(String methodName) {
+ if (!mIsServiceEnabled) {
+ Slog.w(TAG, String.format("Attempted to call %s on unsupported device.", methodName));
+ }
+ return mIsServiceEnabled;
+ }
+
private final AppHibernationServiceStub mServiceStub = new AppHibernationServiceStub(this);
static final class AppHibernationServiceStub extends IAppHibernationService.Stub {
@@ -536,7 +586,7 @@
public static boolean isAppHibernationEnabled() {
return DeviceConfig.getBoolean(
NAMESPACE_APP_HIBERNATION,
- AppHibernationConstants.KEY_APP_HIBERNATION_ENABLED,
+ KEY_APP_HIBERNATION_ENABLED,
false /* defaultValue */);
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a776458..44dcc20 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -339,7 +339,10 @@
SparseIntArray mProfileOwners;
@GuardedBy("this")
- private CheckOpsDelegate mCheckOpsDelegate;
+ private CheckOpsDelegate mAppOpsPolicy;
+
+ @GuardedBy("this")
+ private CheckOpsDelegateDispatcher mCheckOpsDelegateDispatcher;
/**
* Reverse lookup for {@link AppOpsManager#opToSwitch(int)}. Initialized once and never
@@ -1770,6 +1773,17 @@
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
}
+ /**
+ * Sets a policy for handling app ops.
+ *
+ * @param appOpsPolicy The policy.
+ */
+ public void setAppOpsPolicy(@Nullable CheckOpsDelegate appOpsPolicy) {
+ synchronized (AppOpsService.this) {
+ mAppOpsPolicy = appOpsPolicy;
+ }
+ }
+
public void packageRemoved(int uid, String packageName) {
synchronized (this) {
UidState uidState = mUidStates.get(uid);
@@ -2868,13 +2882,19 @@
public CheckOpsDelegate getAppOpsServiceDelegate() {
synchronized (this) {
- return mCheckOpsDelegate;
+ return (mCheckOpsDelegateDispatcher != null)
+ ? mCheckOpsDelegateDispatcher.getCheckOpsDelegate()
+ : null;
}
}
public void setAppOpsServiceDelegate(CheckOpsDelegate delegate) {
synchronized (this) {
- mCheckOpsDelegate = delegate;
+ if (delegate != null) {
+ mCheckOpsDelegateDispatcher = new CheckOpsDelegateDispatcher(delegate);
+ } else {
+ mCheckOpsDelegateDispatcher = null;
+ }
}
}
@@ -2889,19 +2909,28 @@
}
private int checkOperationInternal(int code, int uid, String packageName, boolean raw) {
- final CheckOpsDelegate delegate;
- synchronized (this) {
- delegate = mCheckOpsDelegate;
+ final CheckOpsDelegate policy;
+ final CheckOpsDelegateDispatcher delegateDispatcher;
+ synchronized (AppOpsService.this) {
+ policy = mAppOpsPolicy;
+ delegateDispatcher = mCheckOpsDelegateDispatcher;
}
- if (delegate == null) {
- return checkOperationImpl(code, uid, packageName, raw);
+ if (policy != null) {
+ if (delegateDispatcher != null) {
+ return policy.checkOperation(code, uid, packageName, raw,
+ delegateDispatcher::checkOperationImpl);
+ } else {
+ return policy.checkOperation(code, uid, packageName, raw,
+ AppOpsService.this::checkOperationImpl);
+ }
+ } else if (delegateDispatcher != null) {
+ delegateDispatcher.getCheckOpsDelegate().checkOperation(code, uid,
+ packageName, raw, AppOpsService.this::checkOperationImpl);
}
- return delegate.checkOperation(code, uid, packageName, raw,
- AppOpsService.this::checkOperationImpl);
+ return checkOperationImpl(code, uid, packageName, raw);
}
- private int checkOperationImpl(int code, int uid, String packageName,
- boolean raw) {
+ private int checkOperationImpl(int code, int uid, String packageName, boolean raw) {
verifyIncomingOp(code);
verifyIncomingPackage(packageName, UserHandle.getUserId(uid));
@@ -2956,15 +2985,25 @@
@Override
public int checkAudioOperation(int code, int usage, int uid, String packageName) {
- final CheckOpsDelegate delegate;
- synchronized (this) {
- delegate = mCheckOpsDelegate;
+ final CheckOpsDelegate policy;
+ final CheckOpsDelegateDispatcher delegateDispatcher;
+ synchronized (AppOpsService.this) {
+ policy = mAppOpsPolicy;
+ delegateDispatcher = mCheckOpsDelegateDispatcher;
}
- if (delegate == null) {
- return checkAudioOperationImpl(code, usage, uid, packageName);
+ if (policy != null) {
+ if (delegateDispatcher != null) {
+ return policy.checkAudioOperation(code, usage, uid, packageName,
+ delegateDispatcher::checkAudioOperationImpl);
+ } else {
+ return policy.checkAudioOperation(code, usage, uid, packageName,
+ AppOpsService.this::checkAudioOperationImpl);
+ }
+ } else if (delegateDispatcher != null) {
+ delegateDispatcher.getCheckOpsDelegate().checkAudioOperation(code, usage,
+ uid, packageName, AppOpsService.this::checkAudioOperationImpl);
}
- return delegate.checkAudioOperation(code, usage, uid, packageName,
- AppOpsService.this::checkAudioOperationImpl);
+ return checkAudioOperationImpl(code, usage, uid, packageName);
}
private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
@@ -3078,17 +3117,29 @@
@Override
public int noteOperation(int code, int uid, String packageName, String attributionTag,
boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage) {
- final CheckOpsDelegate delegate;
- synchronized (this) {
- delegate = mCheckOpsDelegate;
+ final CheckOpsDelegate policy;
+ final CheckOpsDelegateDispatcher delegateDispatcher;
+ synchronized (AppOpsService.this) {
+ policy = mAppOpsPolicy;
+ delegateDispatcher = mCheckOpsDelegateDispatcher;
}
- if (delegate == null) {
- return noteOperationImpl(code, uid, packageName, attributionTag,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+ if (policy != null) {
+ if (delegateDispatcher != null) {
+ return policy.noteOperation(code, uid, packageName, attributionTag,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ delegateDispatcher::noteOperationImpl);
+ } else {
+ return policy.noteOperation(code, uid, packageName, attributionTag,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ AppOpsService.this::noteOperationImpl);
+ }
+ } else if (delegateDispatcher != null) {
+ delegateDispatcher.getCheckOpsDelegate().noteOperation(code, uid, packageName,
+ attributionTag, shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ AppOpsService.this::noteOperationImpl);
}
- return delegate.noteOperation(code, uid, packageName, attributionTag,
- shouldCollectAsyncNotedOp, message, shouldCollectMessage,
- AppOpsService.this::noteOperationImpl);
+ return noteOperationImpl(code, uid, packageName, attributionTag,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage);
}
private int noteOperationImpl(int code, int uid, @Nullable String packageName,
@@ -6589,7 +6640,6 @@
}
}
-
/**
* Async task for writing note op stack trace, op code, package name and version to file
* More specifically, writes all the collected ops from {@link #mNoteOpCallerStacktraces}
@@ -6726,4 +6776,34 @@
}
}
}
+
+ private final class CheckOpsDelegateDispatcher {
+ private final @NonNull CheckOpsDelegate mCheckOpsDelegate;
+
+ CheckOpsDelegateDispatcher(@NonNull CheckOpsDelegate checkOpsDelegate) {
+ mCheckOpsDelegate = checkOpsDelegate;
+ }
+
+ public @NonNull CheckOpsDelegate getCheckOpsDelegate() {
+ return mCheckOpsDelegate;
+ }
+
+ public int checkOperationImpl(int code, int uid, String packageName, boolean raw) {
+ return mCheckOpsDelegate.checkOperation(code, uid, packageName, raw,
+ AppOpsService.this::checkOperationImpl);
+ }
+
+ public int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
+ return mCheckOpsDelegate.checkAudioOperation(code, usage, uid, packageName,
+ AppOpsService.this::checkAudioOperationImpl);
+ }
+
+ public int noteOperationImpl(int code, int uid, @Nullable String packageName,
+ @Nullable String featureId, boolean shouldCollectAsyncNotedOp,
+ @Nullable String message, boolean shouldCollectMessage) {
+ return mCheckOpsDelegate.noteOperation(code, uid, packageName, featureId,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage,
+ AppOpsService.this::noteOperationImpl);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java
new file mode 100644
index 0000000..f35a520
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ReEnrollNotificationUtils.java
@@ -0,0 +1,82 @@
+/*
+ * 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.face;
+
+import android.annotation.NonNull;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+
+import com.android.internal.R;
+
+public class ReEnrollNotificationUtils {
+
+ private static final String NOTIFICATION_TAG = "FaceService";
+ private static final int NOTIFICATION_ID = 1;
+
+ public static void showReEnrollmentNotification(@NonNull Context context) {
+ final NotificationManager notificationManager =
+ context.getSystemService(NotificationManager.class);
+
+ final String name =
+ context.getString(R.string.face_recalibrate_notification_name);
+ final String title =
+ context.getString(R.string.face_recalibrate_notification_title);
+ final String content =
+ context.getString(R.string.face_recalibrate_notification_content);
+
+ final Intent intent = new Intent("android.settings.FACE_SETTINGS");
+ intent.setPackage("com.android.settings");
+
+ final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context,
+ 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */,
+ null /* options */, UserHandle.CURRENT);
+
+ final String channelName = "FaceEnrollNotificationChannel";
+
+ final NotificationChannel channel = new NotificationChannel(channelName, name,
+ NotificationManager.IMPORTANCE_HIGH);
+ final Notification notification = new Notification.Builder(context, channelName)
+ .setSmallIcon(R.drawable.ic_lock)
+ .setContentTitle(title)
+ .setContentText(content)
+ .setSubText(name)
+ .setOnlyAlertOnce(true)
+ .setLocalOnly(true)
+ .setAutoCancel(true)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setContentIntent(pendingIntent)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .build();
+
+ notificationManager.createNotificationChannel(channel);
+ notificationManager.notifyAsUser(NOTIFICATION_TAG,
+ NOTIFICATION_ID, notification,
+ UserHandle.CURRENT);
+ }
+
+ public static void cancelNotification(@NonNull Context context) {
+ final NotificationManager notificationManager =
+ context.getSystemService(NotificationManager.class);
+ notificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, UserHandle.CURRENT);
+ }
+
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 8f55402..089cf1e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -41,6 +41,7 @@
import com.android.server.biometrics.sensors.LockoutCache;
import com.android.server.biometrics.sensors.LockoutConsumer;
import com.android.server.biometrics.sensors.LockoutTracker;
+import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils;
import com.android.server.biometrics.sensors.face.UsageStats;
import java.util.ArrayList;
@@ -163,6 +164,9 @@
vibrateError();
}
break;
+ case BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL:
+ ReEnrollNotificationUtils.showReEnrollmentNotification(getContext());
+ break;
default:
break;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 898d81b..0eb51fd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -41,6 +41,7 @@
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.EnrollClient;
import com.android.server.biometrics.sensors.face.FaceUtils;
+import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils;
import java.io.IOException;
import java.util.ArrayList;
@@ -85,6 +86,13 @@
}
@Override
+ public void start(@NonNull Callback callback) {
+ super.start(callback);
+
+ ReEnrollNotificationUtils.cancelNotification(getContext());
+ }
+
+ @Override
public void destroy() {
try {
AidlNativeHandleUtils.close(mPreviewSurface);
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 ee8823e..1b9bd7f 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
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.NotificationManager;
import android.app.SynchronousUserSwitchObserver;
import android.app.UserSwitchObserver;
import android.content.Context;
@@ -71,6 +70,7 @@
import com.android.server.biometrics.sensors.RemovalConsumer;
import com.android.server.biometrics.sensors.face.FaceUtils;
import com.android.server.biometrics.sensors.face.LockoutHalImpl;
+import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils;
import com.android.server.biometrics.sensors.face.ServiceProvider;
import com.android.server.biometrics.sensors.face.UsageStats;
@@ -96,8 +96,6 @@
private static final String TAG = "Face10";
private static final int ENROLL_TIMEOUT_SEC = 75;
- static final String NOTIFICATION_TAG = "FaceService";
- static final int NOTIFICATION_ID = 1;
private boolean mTestHalEnabled;
@@ -109,7 +107,6 @@
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
@NonNull private final LockoutHalImpl mLockoutTracker;
@NonNull private final UsageStats mUsageStats;
- @NonNull private final NotificationManager mNotificationManager;
@NonNull private final Map<Integer, Long> mAuthenticatorIds;
@Nullable private IBiometricsFace mDaemon;
@NonNull private final HalResultController mHalResultController;
@@ -343,7 +340,6 @@
mUsageStats = new UsageStats(context);
mAuthenticatorIds = new HashMap<>();
mLazyDaemon = Face10.this::getDaemon;
- mNotificationManager = mContext.getSystemService(NotificationManager.class);
mLockoutTracker = new LockoutHalImpl();
mLockoutResetDispatcher = lockoutResetDispatcher;
mHalResultController = new HalResultController(sensorId, context, mHandler, mScheduler,
@@ -607,8 +603,7 @@
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
- mNotificationManager.cancelAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
- UserHandle.CURRENT);
+ ReEnrollNotificationUtils.cancelNotification(mContext);
final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index a4b3ac5..3ca51d3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -17,12 +17,7 @@
package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.Context;
-import android.content.Intent;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
@@ -32,7 +27,6 @@
import android.hardware.face.FaceManager;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.R;
@@ -40,6 +34,7 @@
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutTracker;
+import com.android.server.biometrics.sensors.face.ReEnrollNotificationUtils;
import com.android.server.biometrics.sensors.face.UsageStats;
import java.util.ArrayList;
@@ -52,7 +47,7 @@
private static final String TAG = "FaceAuthenticationClient";
- private final NotificationManager mNotificationManager;
+
private final UsageStats mUsageStats;
private final int[] mBiometricPromptIgnoreList;
@@ -72,7 +67,6 @@
owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
lockoutTracker, isKeyguard);
- mNotificationManager = context.getSystemService(NotificationManager.class);
mUsageStats = usageStats;
final Resources resources = getContext().getResources();
@@ -188,41 +182,7 @@
mLastAcquire = acquireInfo;
if (acquireInfo == FaceManager.FACE_ACQUIRED_RECALIBRATE) {
- final String name =
- getContext().getString(R.string.face_recalibrate_notification_name);
- final String title =
- getContext().getString(R.string.face_recalibrate_notification_title);
- final String content =
- getContext().getString(R.string.face_recalibrate_notification_content);
-
- final Intent intent = new Intent("android.settings.FACE_SETTINGS");
- intent.setPackage("com.android.settings");
-
- final PendingIntent pendingIntent = PendingIntent.getActivityAsUser(getContext(),
- 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE /* flags */,
- null /* options */, UserHandle.CURRENT);
-
- final String channelName = "FaceEnrollNotificationChannel";
-
- NotificationChannel channel = new NotificationChannel(channelName, name,
- NotificationManager.IMPORTANCE_HIGH);
- Notification notification = new Notification.Builder(getContext(), channelName)
- .setSmallIcon(R.drawable.ic_lock)
- .setContentTitle(title)
- .setContentText(content)
- .setSubText(name)
- .setOnlyAlertOnce(true)
- .setLocalOnly(true)
- .setAutoCancel(true)
- .setCategory(Notification.CATEGORY_SYSTEM)
- .setContentIntent(pendingIntent)
- .setVisibility(Notification.VISIBILITY_SECRET)
- .build();
-
- mNotificationManager.createNotificationChannel(channel);
- mNotificationManager.notifyAsUser(Face10.NOTIFICATION_TAG,
- Face10.NOTIFICATION_ID, notification,
- UserHandle.CURRENT);
+ ReEnrollNotificationUtils.showReEnrollmentNotification(getContext());
}
final boolean shouldSend = shouldSend(acquireInfo, vendorCode);
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 5076007..322c210 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -61,7 +61,6 @@
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.UiThread;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -207,7 +206,7 @@
new ClipData.Item(contents));
synchronized(mClipboards) {
setPrimaryClipInternal(getClipboard(0), clip,
- android.os.Process.SYSTEM_UID);
+ android.os.Process.SYSTEM_UID, null);
}
}
});
@@ -247,6 +246,8 @@
ClipData primaryClip;
/** UID that set {@link #primaryClip}. */
int primaryClipUid = android.os.Process.NOBODY_UID;
+ /** Application label of the app that set {@link #primaryClip}. */
+ CharSequence mPrimaryClipAppLabel;
final HashSet<String> activePermissionOwners
= new HashSet<String>();
@@ -365,7 +366,7 @@
return;
}
checkDataOwnerLocked(clip, intendingUid);
- setPrimaryClipInternal(clip, intendingUid);
+ setPrimaryClipInternal(clip, intendingUid, callingPackage);
}
}
@@ -378,7 +379,7 @@
intendingUid, intendingUserId)) {
return;
}
- setPrimaryClipInternal(null, intendingUid);
+ setPrimaryClipInternal(null, intendingUid, callingPackage);
}
}
@@ -509,6 +510,11 @@
}
void setPrimaryClipInternal(@Nullable ClipData clip, int uid) {
+ setPrimaryClipInternal(clip, uid, null);
+ }
+
+ private void setPrimaryClipInternal(
+ @Nullable ClipData clip, int uid, @Nullable String sourcePackage) {
// Push clipboard to host, if any
if (mHostClipboardMonitor != null) {
if (clip == null) {
@@ -522,9 +528,20 @@
}
}
+ // Retrieve the app label of the source of the clip data
+ CharSequence sourceAppLabel = null;
+ if (clip != null && sourcePackage != null) {
+ try {
+ sourceAppLabel =
+ mPm.getApplicationLabel(mPm.getApplicationInfo(sourcePackage, 0));
+ } catch (PackageManager.NameNotFoundException e) {
+ // leave label as null
+ }
+ }
+
// Update this user
final int userId = UserHandle.getUserId(uid);
- setPrimaryClipInternal(getClipboard(userId), clip, uid);
+ setPrimaryClipInternal(getClipboard(userId), clip, uid, sourceAppLabel);
// Update related users
List<UserInfo> related = getRelatedProfiles(userId);
@@ -558,7 +575,8 @@
final boolean canCopyIntoProfile = !hasRestriction(
UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id);
if (canCopyIntoProfile) {
- setPrimaryClipInternal(getClipboard(id), clip, uid);
+ setPrimaryClipInternal(
+ getClipboard(id), clip, uid, sourceAppLabel);
}
}
}
@@ -568,6 +586,11 @@
void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip,
int uid) {
+ setPrimaryClipInternal(clipboard, clip, uid, null);
+ }
+
+ private void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip,
+ int uid, @Nullable CharSequence sourceAppLabel) {
revokeUris(clipboard);
clipboard.activePermissionOwners.clear();
if (clip == null && clipboard.primaryClip == null) {
@@ -576,8 +599,10 @@
clipboard.primaryClip = clip;
if (clip != null) {
clipboard.primaryClipUid = uid;
+ clipboard.mPrimaryClipAppLabel = sourceAppLabel;
} else {
clipboard.primaryClipUid = android.os.Process.NOBODY_UID;
+ clipboard.mPrimaryClipAppLabel = null;
}
if (clip != null) {
final ClipDescription description = clip.getDescription();
@@ -861,29 +886,23 @@
&& mAutofillInternal.isAugmentedAutofillServiceForUser(uid, userId)) {
return;
}
- // Load the labels for the calling app and the app that set the clipboard content.
- final long ident = Binder.clearCallingIdentity();
+
try {
- final IPackageManager pm = AppGlobals.getPackageManager();
+ CharSequence callingAppLabel = mPm.getApplicationLabel(
+ mPm.getApplicationInfo(callingPackage, 0));
String message;
- final CharSequence callingLabel = mPm.getApplicationLabel(
- pm.getApplicationInfo(callingPackage, 0, userId));
- final String[] packagesForUid = pm.getPackagesForUid(clipboard.primaryClipUid);
- if (packagesForUid != null && packagesForUid.length > 0) {
- final CharSequence clipLabel = mPm.getApplicationLabel(
- pm.getApplicationInfo(packagesForUid[0], 0,
- UserHandle.getUserId(clipboard.primaryClipUid)));
- message = callingLabel + " pasted from " + clipLabel;
+ if (clipboard.mPrimaryClipAppLabel != null) {
+ message = callingAppLabel + " pasted from " + clipboard.mPrimaryClipAppLabel;
} else {
- message = callingLabel + " pasted from clipboard";
+ message = callingAppLabel + " pasted from clipboard";
}
Slog.i(TAG, message);
- Toast.makeText(getContext(), UiThread.get().getLooper(), message, Toast.LENGTH_SHORT)
- .show();
- } catch (RemoteException e) {
- /* ignore */
- } finally {
- Binder.restoreCallingIdentity(ident);
+ Binder.withCleanCallingIdentity(() ->
+ Toast.makeText(getContext(), UiThread.get().getLooper(), message,
+ Toast.LENGTH_SHORT)
+ .show());
+ } catch (PackageManager.NameNotFoundException e) {
+ // do nothing
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 713ac73..01ac81fb 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1510,7 +1510,7 @@
if (start != -1) ranges.add(new UidRange(start, stop));
} else if (disallowedApplications != null) {
// Add all ranges for user skipping UIDs for disallowedApplications.
- final UidRange userRange = UidRange.createForUser(userId);
+ final UidRange userRange = UidRange.createForUser(UserHandle.of(userId));
int start = userRange.start;
for (int uid : getAppsUids(disallowedApplications, userId)) {
if (uid == start) {
@@ -1523,7 +1523,7 @@
if (start <= userRange.stop) ranges.add(new UidRange(start, userRange.stop));
} else {
// Add all UIDs for the user.
- ranges.add(UidRange.createForUser(userId));
+ ranges.add(UidRange.createForUser(UserHandle.of(userId)));
}
}
@@ -1532,7 +1532,7 @@
private static List<UidRange> uidRangesForUser(int userId, Set<UidRange> existingRanges) {
// UidRange#createForUser returns the entire range of UIDs available to a macro-user.
// This is something like 0-99999 ; {@see UserHandle#PER_USER_RANGE}
- final UidRange userRange = UidRange.createForUser(userId);
+ final UidRange userRange = UidRange.createForUser(UserHandle.of(userId));
final List<UidRange> ranges = new ArrayList<>();
for (UidRange range : existingRanges) {
if (userRange.containsRange(range)) {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index fe89903..7b9ca37 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -264,6 +264,10 @@
private final SyncLogger mLogger;
+ // NOTE: this is a temporary allow-list for testing purposes; it will be removed before release.
+ private final String[] mEjSyncAllowedPackages = new String[]{
+ "com.google.android.google", "com.android.frameworks.servicestests"};
+
private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) {
for (JobInfo job: pendingJobs) {
if (job.getId() == jobId) {
@@ -983,6 +987,14 @@
}
}
+ final boolean scheduleAsEj =
+ extras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false);
+ // NOTE: this is a temporary check for internal testing - to be removed before release.
+ if (scheduleAsEj && !ArrayUtils.contains(mEjSyncAllowedPackages, callingPackage)) {
+ throw new IllegalArgumentException(
+ callingPackage + " is not allowed to schedule a sync as an EJ yet.");
+ }
+
for (AccountAndUser account : accounts) {
// If userId is specified, do not sync accounts of other users
if (userId >= UserHandle.USER_SYSTEM && account.userId >= UserHandle.USER_SYSTEM
@@ -1490,6 +1502,12 @@
+ logSafe(syncOperation.target));
backoff = new Pair<Long, Long>(SyncStorageEngine.NOT_IN_BACKOFF_MODE,
SyncStorageEngine.NOT_IN_BACKOFF_MODE);
+ } else {
+ // if an EJ is being backed-off but doesn't have SYNC_EXTRAS_IGNORE_BACKOFF set,
+ // reschedule it as a regular job
+ if (syncOperation.isScheduledAsExpeditedJob()) {
+ syncOperation.scheduleEjAsRegularJob = true;
+ }
}
long now = SystemClock.elapsedRealtime();
long backoffDelay = backoff.first == SyncStorageEngine.NOT_IN_BACKOFF_MODE ? 0
@@ -1640,6 +1658,10 @@
b.setRequiresCharging(true);
}
+ if (syncOperation.isScheduledAsExpeditedJob() && !syncOperation.scheduleEjAsRegularJob) {
+ b.setExpedited(true);
+ }
+
if (syncOperation.syncExemptionFlag
== ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP) {
DeviceIdleInternal dic =
@@ -3951,6 +3973,9 @@
if (key.equals(ContentResolver.SYNC_EXTRAS_EXPEDITED)) {
return true;
}
+ if (key.equals(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB)) {
+ return true;
+ }
if (key.equals(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS)) {
return true;
}
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 4787635..c8654d1 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -103,6 +103,13 @@
/** Stores the number of times this sync operation failed and had to be retried. */
int retries;
+ /**
+ * Indicates if a sync that was originally scheduled as an EJ is being re-scheduled as a
+ * regular job. Specifically, this will be {@code true} if a sync is being backed-off but
+ * {@link ContentResolver#SYNC_EXTRAS_IGNORE_BACKOFF} is not set.
+ */
+ boolean scheduleEjAsRegularJob;
+
/** jobId of the JobScheduler job corresponding to this sync */
public int jobId;
@@ -408,6 +415,12 @@
if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false)) {
sb.append(" EXPEDITED");
}
+ if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false)) {
+ sb.append(" EXPEDITED-JOB");
+ if (scheduleEjAsRegularJob) {
+ sb.append("(scheduled-as-regular)");
+ }
+ }
switch (syncExemptionFlag) {
case ContentResolver.SYNC_EXEMPTION_NONE:
break;
@@ -537,6 +550,11 @@
return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING, false);
}
+ boolean isScheduledAsExpeditedJob() {
+ return mImmutableExtras.getBoolean(
+ ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, false);
+ }
+
boolean isAppStandbyExempted() {
return syncExemptionFlag != ContentResolver.SYNC_EXEMPTION_NONE;
}
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index a62f67a..30cbf27 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -61,7 +61,10 @@
private static final Plog PLOG = Plog.createSystemPlog(TAG);
@Nullable
- public static BrightnessMappingStrategy create(Resources resources) {
+ public static BrightnessMappingStrategy create(Resources resources,
+ DisplayDeviceConfig displayDeviceConfig) {
+
+ // Display independent values
float[] luxLevels = getLuxLevels(resources.getIntArray(
com.android.internal.R.array.config_autoBrightnessLevels));
int[] brightnessLevelsBacklight = resources.getIntArray(
@@ -71,32 +74,22 @@
float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
1, 1);
-
- float[] nitsRange = getFloatArray(resources.obtainTypedArray(
- com.android.internal.R.array.config_screenBrightnessNits));
- int[] backlightRange = resources.getIntArray(
- com.android.internal.R.array.config_screenBrightnessBacklight);
-
long shortTermModelTimeout = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessShortTermModelTimeout);
- if (isValidMapping(nitsRange, backlightRange)
+ // Display dependent values - used for physical mapping strategy nits -> brightness
+ final float[] nitsRange = displayDeviceConfig.getNits();
+ final float[] brightnessRange = displayDeviceConfig.getBrightness();
+
+ if (isValidMapping(nitsRange, brightnessRange)
&& isValidMapping(luxLevels, brightnessLevelsNits)) {
- int minimumBacklight = resources.getInteger(
- com.android.internal.R.integer.config_screenBrightnessSettingMinimum);
- int maximumBacklight = resources.getInteger(
- com.android.internal.R.integer.config_screenBrightnessSettingMaximum);
- if (backlightRange[0] > minimumBacklight
- || backlightRange[backlightRange.length - 1] < maximumBacklight) {
- Slog.w(TAG, "Screen brightness mapping does not cover whole range of available " +
- "backlight values, autobrightness functionality may be impaired.");
- }
+
BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
luxLevels, brightnessLevelsNits);
builder.setShortTermModelTimeoutMillis(shortTermModelTimeout);
builder.setShortTermModelLowerLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
- return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
+ return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange,
autoBrightnessAdjustmentMaxGamma);
} else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
@@ -264,11 +257,11 @@
public abstract boolean setAutoBrightnessAdjustment(float adjustment);
/**
- * Converts the provided backlight value to nits if possible.
+ * Converts the provided brightness value to nits if possible.
*
- * Returns -1.0f if there's no available mapping for the backlight to nits.
+ * Returns -1.0f if there's no available mapping for the brightness to nits.
*/
- public abstract float convertToNits(int backlight);
+ public abstract float convertToNits(float brightness);
/**
* Adds a user interaction data point to the brightness mapping.
@@ -603,7 +596,7 @@
}
@Override
- public float convertToNits(int backlight) {
+ public float convertToNits(float brightness) {
return -1.0f;
}
@@ -701,37 +694,39 @@
// in nits.
private Spline mBrightnessSpline;
- // A spline mapping from nits to the corresponding backlight value, normalized to the range
+ // A spline mapping from nits to the corresponding brightness value, normalized to the range
// [0, 1.0].
- private Spline mNitsToBacklightSpline;
+ private Spline mNitsToBrightnessSpline;
+
+ // A spline mapping from the system brightness value, normalized to the range [0, 1.0], to
+ // a brightness in nits.
+ private Spline mBrightnessToNitsSpline;
// The default brightness configuration.
private final BrightnessConfiguration mDefaultConfig;
- // A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to
- // a brightness in nits.
- private Spline mBacklightToNitsSpline;
-
- private float[] mNits;
- private int[] mBacklight;
+ private final float[] mNits;
+ private final float[] mBrightness;
private boolean mBrightnessRangeAdjustmentApplied;
- private float mMaxGamma;
+ private final float mMaxGamma;
private float mAutoBrightnessAdjustment;
private float mUserLux;
private float mUserBrightness;
public PhysicalMappingStrategy(BrightnessConfiguration config, float[] nits,
- int[] backlight, float maxGamma) {
- Preconditions.checkArgument(nits.length != 0 && backlight.length != 0,
- "Nits and backlight arrays must not be empty!");
- Preconditions.checkArgument(nits.length == backlight.length,
- "Nits and backlight arrays must be the same length!");
+ float[] brightness, float maxGamma) {
+
+ Preconditions.checkArgument(nits.length != 0 && brightness.length != 0,
+ "Nits and brightness arrays must not be empty!");
+
+ Preconditions.checkArgument(nits.length == brightness.length,
+ "Nits and brightness arrays must be the same length!");
Objects.requireNonNull(config);
Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
- Preconditions.checkArrayElementsInRange(backlight,
- PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON, "backlight");
+ Preconditions.checkArrayElementsInRange(brightness,
+ PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, "brightness");
mMaxGamma = maxGamma;
mAutoBrightnessAdjustment = 0;
@@ -739,7 +734,7 @@
mUserBrightness = -1;
mNits = nits;
- mBacklight = backlight;
+ mBrightness = brightness;
computeNitsBrightnessSplines(mNits);
mDefaultConfig = config;
@@ -784,15 +779,15 @@
public float getBrightness(float lux, String packageName,
@ApplicationInfo.Category int category) {
float nits = mBrightnessSpline.interpolate(lux);
- float backlight = mNitsToBacklightSpline.interpolate(nits);
+ float brightness = mNitsToBrightnessSpline.interpolate(nits);
// Correct the brightness according to the current application and its category, but
- // only if no user data point is set (as this will oevrride the user setting).
+ // only if no user data point is set (as this will override the user setting).
if (mUserLux == -1) {
- backlight = correctBrightness(backlight, packageName, category);
+ brightness = correctBrightness(brightness, packageName, category);
} else if (mLoggingEnabled) {
Slog.d(TAG, "user point set, correction not applied");
}
- return backlight;
+ return brightness;
}
@Override
@@ -817,8 +812,8 @@
}
@Override
- public float convertToNits(int backlight) {
- return mBacklightToNitsSpline.interpolate(normalizeAbsoluteBrightness(backlight));
+ public float convertToNits(float brightness) {
+ return mBrightnessToNitsSpline.interpolate(brightness);
}
@Override
@@ -884,7 +879,8 @@
pw.println("PhysicalMappingStrategy");
pw.println(" mConfig=" + mConfig);
pw.println(" mBrightnessSpline=" + mBrightnessSpline);
- pw.println(" mNitsToBacklightSpline=" + mNitsToBacklightSpline);
+ pw.println(" mNitsToBrightnessSpline=" + mNitsToBrightnessSpline);
+ pw.println(" mBrightnessToNitsSpline=" + mBrightnessToNitsSpline);
pw.println(" mMaxGamma=" + mMaxGamma);
pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
pw.println(" mUserLux=" + mUserLux);
@@ -894,31 +890,25 @@
}
private void computeNitsBrightnessSplines(float[] nits) {
- final int len = nits.length;
- float[] normalizedBacklight = new float[len];
- for (int i = 0; i < len; i++) {
- normalizedBacklight[i] = normalizeAbsoluteBrightness(mBacklight[i]);
- }
-
- mNitsToBacklightSpline = Spline.createSpline(nits, normalizedBacklight);
- mBacklightToNitsSpline = Spline.createSpline(normalizedBacklight, nits);
+ mNitsToBrightnessSpline = Spline.createSpline(nits, mBrightness);
+ mBrightnessToNitsSpline = Spline.createSpline(mBrightness, nits);
}
private void computeSpline() {
Pair<float[], float[]> defaultCurve = mConfig.getCurve();
float[] defaultLux = defaultCurve.first;
float[] defaultNits = defaultCurve.second;
- float[] defaultBacklight = new float[defaultNits.length];
- for (int i = 0; i < defaultBacklight.length; i++) {
- defaultBacklight[i] = mNitsToBacklightSpline.interpolate(defaultNits[i]);
+ float[] defaultBrightness = new float[defaultNits.length];
+ for (int i = 0; i < defaultBrightness.length; i++) {
+ defaultBrightness[i] = mNitsToBrightnessSpline.interpolate(defaultNits[i]);
}
- Pair<float[], float[]> curve = getAdjustedCurve(defaultLux, defaultBacklight, mUserLux,
+ Pair<float[], float[]> curve = getAdjustedCurve(defaultLux, defaultBrightness, mUserLux,
mUserBrightness, mAutoBrightnessAdjustment, mMaxGamma);
float[] lux = curve.first;
- float[] backlight = curve.second;
- float[] nits = new float[backlight.length];
+ float[] brightness = curve.second;
+ float[] nits = new float[brightness.length];
for (int i = 0; i < nits.length; i++) {
- nits[i] = mBacklightToNitsSpline.interpolate(backlight[i]);
+ nits[i] = mBrightnessToNitsSpline.interpolate(brightness[i]);
}
mBrightnessSpline = Spline.createSpline(lux, nits);
}
@@ -926,7 +916,7 @@
private float getUnadjustedBrightness(float lux) {
Pair<float[], float[]> curve = mConfig.getCurve();
Spline spline = Spline.createSpline(curve.first, curve.second);
- return mNitsToBacklightSpline.interpolate(spline.interpolate(lux));
+ return mNitsToBrightnessSpline.interpolate(spline.interpolate(lux));
}
private float correctBrightness(float brightness, String packageName, int category) {
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 49328f1..0071b2f 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -18,9 +18,12 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.content.res.Resources;
import android.os.Environment;
import android.os.PowerManager;
+import android.util.MathUtils;
import android.util.Slog;
+import android.util.Spline;
import android.view.DisplayAddress;
import com.android.internal.R;
@@ -72,15 +75,31 @@
private final Context mContext;
+ // Nits and backlight values that are loaded from either the display device config file, or
+ // config.xml. These are the raw values and just used for the dumpsys
+ private float[] mRawNits;
+ private float[] mRawBacklight;
+
+ // These arrays are calculated from the raw arrays, but clamped to contain values equal to and
+ // between mBacklightMinimum and mBacklightMaximum. These three arrays should all be the same
+ // length
+ // Nits array that is used to store the entire range of nits values that the device supports
private float[] mNits;
+ // Backlight array holds the values that the HAL uses to display the corresponding nits values
+ private float[] mBacklight;
+ // Purely an array that covers the ranges of values 0.0 - 1.0, indicating the system brightness
+ // for the corresponding values above
private float[] mBrightness;
- private float mBrightnessMinimum = Float.NaN;
- private float mBrightnessMaximum = Float.NaN;
+
+ private float mBacklightMinimum = Float.NaN;
+ private float mBacklightMaximum = Float.NaN;
private float mBrightnessDefault = Float.NaN;
private float mBrightnessRampFastDecrease = Float.NaN;
private float mBrightnessRampFastIncrease = Float.NaN;
private float mBrightnessRampSlowDecrease = Float.NaN;
private float mBrightnessRampSlowIncrease = Float.NaN;
+ private Spline mBrightnessToBacklightSpline;
+ private Spline mBacklightToBrightnessSpline;
private List<String> mQuirks;
private boolean mIsHighBrightnessModeEnabled = false;
private HighBrightnessModeData mHbmData;
@@ -167,7 +186,7 @@
}
/**
- * Return the brightness mapping nits array if one is defined in the configuration file.
+ * Return the brightness mapping nits array.
*
* @return The brightness mapping nits array.
*/
@@ -176,22 +195,40 @@
}
/**
- * Return the brightness mapping value array if one is defined in the configuration file.
+ * Return the brightness mapping backlight array.
*
- * @return The brightness mapping value array.
+ * @return The backlight mapping value array.
+ */
+ public float[] getBacklight() {
+ return mBacklight;
+ }
+
+ /**
+ * Calculates the backlight value, as recognised by the HAL, from the brightness value
+ * given that the rest of the system deals with.
+ *
+ * @param brightness value on the framework scale of 0-1
+ * @return backlight value on the HAL scale of 0-1
+ */
+ public float getBacklightFromBrightness(float brightness) {
+ return mBrightnessToBacklightSpline.interpolate(brightness);
+ }
+
+ /**
+ * Return an array of equal length to backlight and nits, that covers the entire system
+ * brightness range of 0.0-1.0.
+ *
+ * @return brightness array
*/
public float[] getBrightness() {
return mBrightness;
}
- public float getBrightnessMinimum() {
- return mBrightnessMinimum;
- }
-
- public float getBrightnessMaximum() {
- return mBrightnessMaximum;
- }
-
+ /**
+ * Return the default brightness on a scale of 0.0f - 1.0f
+ *
+ * @return default brightness
+ */
public float getBrightnessDefault() {
return mBrightnessDefault;
}
@@ -237,10 +274,15 @@
@Override
public String toString() {
String str = "DisplayDeviceConfig{"
- + "mBrightness=" + Arrays.toString(mBrightness)
+ + "mBacklight=" + Arrays.toString(mBacklight)
+ ", mNits=" + Arrays.toString(mNits)
- + ", mBrightnessMinimum=" + mBrightnessMinimum
- + ", mBrightnessMaximum=" + mBrightnessMaximum
+ + ", mRawBacklight=" + Arrays.toString(mRawBacklight)
+ + ", mRawNits=" + Arrays.toString(mRawNits)
+ + ", mBrightness=" + Arrays.toString(mBrightness)
+ + ", mBrightnessToBacklightSpline=" + mBrightnessToBacklightSpline
+ + ", mBacklightToBrightnessSpline=" + mBacklightToBrightnessSpline
+ + ", mBacklightMinimum=" + mBacklightMinimum
+ + ", mBacklightMaximum=" + mBacklightMaximum
+ ", mBrightnessDefault=" + mBrightnessDefault
+ ", mQuirks=" + mQuirks
+ ", isHbmEnabled=" + mIsHighBrightnessModeEnabled
@@ -253,10 +295,6 @@
return str;
}
- private float getMaxBrightness() {
- return mBrightness[mBrightness.length - 1];
- }
-
private static DisplayDeviceConfig getConfigFromSuffix(Context context, File baseDirectory,
String suffixFormat, long idNumber) {
@@ -264,7 +302,6 @@
final String filename = String.format(CONFIG_FILE_FORMAT, suffix);
final File filePath = Environment.buildPath(
baseDirectory, ETC_DIR, DISPLAY_CONFIG_DIR, filename);
-
if (filePath.exists()) {
final DisplayDeviceConfig config = new DisplayDeviceConfig(context);
config.initFromFile(filePath);
@@ -299,9 +336,9 @@
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
final DisplayConfiguration config = XmlParser.read(in);
if (config != null) {
- loadBrightnessMap(config);
loadBrightnessDefaultFromDdcXml(config);
loadBrightnessConstraintsFromConfigXml();
+ loadBrightnessMap(config);
loadHighBrightnessModeData(config);
loadQuirks(config);
loadBrightnessRamps(config);
@@ -318,13 +355,20 @@
// If no ddc exists, use config.xml
loadBrightnessDefaultFromConfigXml();
loadBrightnessConstraintsFromConfigXml();
+ loadBrightnessMapFromConfigXml();
loadBrightnessRampsFromConfigXml();
}
private void initFromPmValues() {
- mBrightnessMinimum = PowerManager.BRIGHTNESS_MIN;
- mBrightnessMaximum = PowerManager.BRIGHTNESS_MAX;
+ // Set all to basic values
+ mBacklightMinimum = PowerManager.BRIGHTNESS_MIN;
+ mBacklightMaximum = PowerManager.BRIGHTNESS_MAX;
mBrightnessDefault = BRIGHTNESS_DEFAULT;
+ mBrightnessRampFastDecrease = PowerManager.BRIGHTNESS_MAX;
+ mBrightnessRampFastIncrease = PowerManager.BRIGHTNESS_MAX;
+ mBrightnessRampSlowDecrease = PowerManager.BRIGHTNESS_MAX;
+ mBrightnessRampSlowIncrease = PowerManager.BRIGHTNESS_MAX;
+ setSimpleMappingStrategyValues();
}
private void loadBrightnessDefaultFromDdcXml(DisplayConfiguration config) {
@@ -364,24 +408,27 @@
final float max = mContext.getResources().getFloat(com.android.internal.R.dimen
.config_screenBrightnessSettingMaximumFloat);
if (min == INVALID_BRIGHTNESS_IN_CONFIG || max == INVALID_BRIGHTNESS_IN_CONFIG) {
- mBrightnessMinimum = BrightnessSynchronizer.brightnessIntToFloat(
+ mBacklightMinimum = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
.config_screenBrightnessSettingMinimum));
- mBrightnessMaximum = BrightnessSynchronizer.brightnessIntToFloat(
+ mBacklightMaximum = BrightnessSynchronizer.brightnessIntToFloat(
mContext.getResources().getInteger(com.android.internal.R.integer
.config_screenBrightnessSettingMaximum));
} else {
- mBrightnessMinimum = min;
- mBrightnessMaximum = max;
+ mBacklightMinimum = min;
+ mBacklightMaximum = max;
}
}
private void loadBrightnessMap(DisplayConfiguration config) {
final NitsMap map = config.getScreenBrightnessMap();
- // Map may not exist in config file
+ // Map may not exist in display device config
if (map == null) {
+ loadBrightnessMapFromConfigXml();
return;
}
+
+ // Use the (preferred) display device config mapping
final List<Point> points = map.getPoint();
final int size = points.size();
@@ -408,8 +455,123 @@
}
++i;
}
- mNits = nits;
- mBrightness = backlight;
+ mRawNits = nits;
+ mRawBacklight = backlight;
+ constrainNitsAndBacklightArrays();
+ }
+
+ private void loadBrightnessMapFromConfigXml() {
+ // Use the config.xml mapping
+ final Resources res = mContext.getResources();
+ final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray(
+ com.android.internal.R.array.config_screenBrightnessNits));
+ final int[] sysBrightness = res.getIntArray(
+ com.android.internal.R.array.config_screenBrightnessBacklight);
+ final float[] sysBrightnessFloat = new float[sysBrightness.length];
+
+ for (int i = 0; i < sysBrightness.length; i++) {
+ sysBrightnessFloat[i] = BrightnessSynchronizer.brightnessIntToFloat(
+ sysBrightness[i]);
+ }
+
+ // These arrays are allowed to be empty, we set null values so that
+ // BrightnessMappingStrategy will create a SimpleMappingStrategy instead.
+ if (sysBrightnessFloat.length == 0 || sysNits.length == 0) {
+ setSimpleMappingStrategyValues();
+ return;
+ }
+
+ mRawNits = sysNits;
+ mRawBacklight = sysBrightnessFloat;
+ constrainNitsAndBacklightArrays();
+ }
+
+ private void setSimpleMappingStrategyValues() {
+ // No translation from backlight to brightness should occur if we are using a
+ // SimpleMappingStrategy (ie they should be the same) so the splines are
+ // set to be linear, between 0.0 and 1.0
+ mNits = null;
+ mBacklight = null;
+ float[] simpleMappingStrategyArray = new float[]{0.0f, 1.0f};
+ mBrightnessToBacklightSpline = Spline.createSpline(simpleMappingStrategyArray,
+ simpleMappingStrategyArray);
+ mBacklightToBrightnessSpline = Spline.createSpline(simpleMappingStrategyArray,
+ simpleMappingStrategyArray);
+ }
+
+ /**
+ * Change the nits and backlight arrays, so that they cover only the allowed backlight values
+ * Use the brightness minimum and maximum values to clamp these arrays.
+ */
+ private void constrainNitsAndBacklightArrays() {
+ if (mRawBacklight[0] > mBacklightMinimum
+ || mRawBacklight[mRawBacklight.length - 1] < mBacklightMaximum
+ || mBacklightMinimum > mBacklightMaximum) {
+ throw new IllegalStateException("Min or max values are invalid"
+ + "; raw min=" + mRawBacklight[0]
+ + "; raw max=" + mRawBacklight[mRawBacklight.length - 1]
+ + "; backlight min=" + mBacklightMinimum
+ + "; backlight max=" + mBacklightMaximum);
+ }
+
+ float[] newNits = new float[mRawBacklight.length];
+ float[] newBacklight = new float[mRawBacklight.length];
+ // Find the starting index of the clamped arrays. This may be less than the min so
+ // we'll need to clamp this value still when actually doing the remapping.
+ int newStart = 0;
+ for (int i = 0; i < mRawBacklight.length - 1; i++) {
+ if (mRawBacklight[i + 1] > mBacklightMinimum) {
+ newStart = i;
+ break;
+ }
+ }
+
+ boolean isLastValue = false;
+ int newIndex = 0;
+ for (int i = newStart; i < mRawBacklight.length && !isLastValue; i++) {
+ newIndex = i - newStart;
+ final float newBacklightVal;
+ final float newNitsVal;
+ isLastValue = mRawBacklight[i] > mBacklightMaximum
+ || i >= mRawBacklight.length - 1;
+ // Clamp beginning and end to valid backlight values.
+ if (newIndex == 0) {
+ newBacklightVal = MathUtils.max(mRawBacklight[i], mBacklightMinimum);
+ newNitsVal = rawBacklightToNits(i, newBacklightVal);
+ } else if (isLastValue) {
+ newBacklightVal = MathUtils.min(mRawBacklight[i], mBacklightMaximum);
+ newNitsVal = rawBacklightToNits(i - 1, newBacklightVal);
+ } else {
+ newBacklightVal = mRawBacklight[i];
+ newNitsVal = mRawNits[i];
+ }
+ newBacklight[newIndex] = newBacklightVal;
+ newNits[newIndex] = newNitsVal;
+ }
+ mBacklight = Arrays.copyOf(newBacklight, newIndex + 1);
+ mNits = Arrays.copyOf(newNits, newIndex + 1);
+ createBacklightConversionSplines();
+ }
+
+ private float rawBacklightToNits(int i, float backlight) {
+ return MathUtils.map(mRawBacklight[i], mRawBacklight[i + 1],
+ mRawNits[i], mRawNits[i + 1], backlight);
+ }
+
+ // This method creates a brightness spline that is of equal length with proportional increments
+ // to the backlight spline. The values of this array range from 0.0f to 1.0f instead of the
+ // potential constrained range that the backlight array covers
+ // These splines are used to convert from the system brightness value to the HAL backlight
+ // value
+ private void createBacklightConversionSplines() {
+ mBrightness = new float[mBacklight.length];
+ for (int i = 0; i < mBrightness.length; i++) {
+ mBrightness[i] = MathUtils.map(mBacklight[0],
+ mBacklight[mBacklight.length - 1],
+ PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, mBacklight[i]);
+ }
+ mBrightnessToBacklightSpline = Spline.createSpline(mBrightness, mBacklight);
+ mBacklightToBrightnessSpline = Spline.createSpline(mBacklight, mBrightness);
}
private void loadQuirks(DisplayConfiguration config) {
@@ -425,12 +587,14 @@
mIsHighBrightnessModeEnabled = hbm.getEnabled();
mHbmData = new HighBrightnessModeData();
mHbmData.minimumLux = hbm.getMinimumLux_all().floatValue();
- mHbmData.transitionPoint = hbm.getTransitionPoint_all().floatValue();
- if (mHbmData.transitionPoint >= getMaxBrightness()) {
+ float transitionPointBacklightScale = hbm.getTransitionPoint_all().floatValue();
+ if (transitionPointBacklightScale >= mBacklightMaximum) {
throw new IllegalArgumentException("HBM transition point invalid. "
+ mHbmData.transitionPoint + " is not less than "
- + getMaxBrightness());
+ + mBacklightMaximum);
}
+ mHbmData.transitionPoint =
+ mBacklightToBrightnessSpline.interpolate(transitionPointBacklightScale);
final HbmTiming hbmTiming = hbm.getTiming_all();
mHbmData.timeWindowMillis = hbmTiming.getTimeWindowSecs_all().longValue() * 1000;
mHbmData.timeMaxMillis = hbmTiming.getTimeMaxSecs_all().longValue() * 1000;
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 62cf86b..2005a74 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -190,12 +190,6 @@
// The dim screen brightness.
private final float mScreenBrightnessDimConfig;
- // The minimum allowed brightness.
- private final float mScreenBrightnessRangeMinimum;
-
- // The maximum allowed brightness.
- private final float mScreenBrightnessRangeMaximum;
-
private final float mScreenBrightnessDefault;
// The minimum allowed brightness while in VR.
@@ -443,8 +437,6 @@
final Resources resources = context.getResources();
- final float screenBrightnessSettingMinimumFloat = clampAbsoluteBrightness(
- pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM));
// DOZE AND DIM SETTINGS
mScreenBrightnessDozeConfig = clampAbsoluteBrightness(
@@ -453,10 +445,6 @@
pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
// NORMAL SCREEN SETTINGS
- mScreenBrightnessRangeMinimum =
- Math.min(screenBrightnessSettingMinimumFloat, mScreenBrightnessDimConfig);
- mScreenBrightnessRangeMaximum = clampAbsoluteBrightness(
- pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM));
mScreenBrightnessDefault = clampAbsoluteBrightness(
mLogicalDisplay.getDisplayInfoLocked().brightnessDefault);
@@ -545,12 +533,14 @@
com.android.internal.R.string.config_displayLightSensorType);
Sensor lightSensor = findDisplayLightSensor(lightSensorType);
- mBrightnessMapper = BrightnessMappingStrategy.create(resources);
+ final DisplayDeviceConfig ddc =
+ logicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig();
+ mBrightnessMapper = BrightnessMappingStrategy.create(resources, ddc);
if (mBrightnessMapper != null) {
mAutomaticBrightnessController = new AutomaticBrightnessController(this,
handler.getLooper(), sensorManager, lightSensor, mBrightnessMapper,
- lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,
- mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
+ lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN,
+ PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
screenBrightnessThresholds, logicalDisplay, context);
@@ -838,9 +828,8 @@
noteScreenBrightness(mPowerState.getScreenBrightness());
// Initialize all of the brightness tracking state
- final float brightness = convertToNits(BrightnessSynchronizer.brightnessFloatToInt(
- mPowerState.getScreenBrightness()));
- if (brightness >= 0.0f) {
+ final float brightness = convertToNits(mPowerState.getScreenBrightness());
+ if (brightness >= PowerManager.BRIGHTNESS_MIN) {
mBrightnessTracker.start(brightness);
}
@@ -1151,10 +1140,10 @@
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
- if (brightnessState > mScreenBrightnessRangeMinimum) {
+ if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
brightnessState = Math.max(Math.min(brightnessState
- SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
- mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
+ mScreenBrightnessDimConfig), PowerManager.BRIGHTNESS_MIN);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
}
if (!mAppliedDimming) {
@@ -1168,12 +1157,11 @@
// If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
// as long as it is above the minimum threshold.
if (mPowerRequest.lowPowerMode) {
- if (brightnessState > mScreenBrightnessRangeMinimum) {
+ if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
- brightnessState = Math.max(lowPowerBrightnessFloat,
- mScreenBrightnessRangeMinimum);
+ brightnessState = Math.max(lowPowerBrightnessFloat, PowerManager.BRIGHTNESS_MIN);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
}
if (!mAppliedLowPower) {
@@ -1258,9 +1246,8 @@
// slider event so notify as if the system changed the brightness.
userInitiatedChange = false;
}
- notifyBrightnessChanged(
- BrightnessSynchronizer.brightnessFloatToInt(brightnessState),
- userInitiatedChange, hadUserBrightnessPoint);
+ notifyBrightnessChanged(brightnessState, userInitiatedChange,
+ hadUserBrightnessPoint);
}
}
@@ -1487,17 +1474,17 @@
private float clampScreenBrightness(float value) {
if (Float.isNaN(value)) {
- return mScreenBrightnessRangeMinimum;
+ return PowerManager.BRIGHTNESS_MIN;
}
return MathUtils.constrain(
- value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
+ value, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
}
// Checks whether the brightness is within the valid brightness range, not including the off or
// invalid states.
private boolean isValidBrightnessValue(float brightnessState) {
- return brightnessState >= mScreenBrightnessRangeMinimum
- && brightnessState <= mScreenBrightnessRangeMaximum;
+ return brightnessState >= PowerManager.BRIGHTNESS_MIN
+ && brightnessState <= PowerManager.BRIGHTNESS_MAX;
}
private void animateScreenBrightness(float target, float rate) {
@@ -1874,7 +1861,7 @@
return true;
}
- private void notifyBrightnessChanged(int brightness, boolean userInitiated,
+ private void notifyBrightnessChanged(float brightness, boolean userInitiated,
boolean hadUserDataPoint) {
final float brightnessInNits = convertToNits(brightness);
if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f
@@ -1891,9 +1878,9 @@
}
}
- private float convertToNits(int backlight) {
+ private float convertToNits(float brightness) {
if (mBrightnessMapper != null) {
- return mBrightnessMapper.convertToNits(backlight);
+ return mBrightnessMapper.convertToNits(brightness);
} else {
return -1.0f;
}
@@ -1972,12 +1959,9 @@
pw.println();
pw.println("Display Power Controller Configuration:");
- pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
- pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
pw.println(" mScreenBrightnessRangeDefault=" + mScreenBrightnessDefault);
pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
- pw.println(" mScreenBrightnessDefault=" + mScreenBrightnessDefault);
pw.println(" mScreenBrightnessForVrRangeMinimum=" + mScreenBrightnessForVrRangeMinimum);
pw.println(" mScreenBrightnessForVrRangeMaximum=" + mScreenBrightnessForVrRangeMaximum);
pw.println(" mScreenBrightnessForVrDefault=" + mScreenBrightnessForVrDefault);
@@ -2109,10 +2093,6 @@
}
}
- private static int clampAbsoluteBrightness(int value) {
- return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
- }
-
private static float clampAbsoluteBrightness(float value) {
return MathUtils.constrain(value, PowerManager.BRIGHTNESS_MIN,
PowerManager.BRIGHTNESS_MAX);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 4bbf227..48f335d 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -30,7 +30,6 @@
import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.Spline;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.DisplayCutout;
@@ -210,8 +209,7 @@
private SurfaceControl.DisplayMode[] mSfDisplayModes;
// The active display mode in SurfaceFlinger
private SurfaceControl.DisplayMode mActiveSfDisplayMode;
- private Spline mSystemBrightnessToNits;
- private Spline mNitsToHalBrightness;
+ private DisplayDeviceConfig mDisplayDeviceConfig;
private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides =
new DisplayEventReceiver.FrameRateOverride[0];
@@ -410,16 +408,13 @@
@Override
public DisplayDeviceConfig getDisplayDeviceConfig() {
if (mDisplayDeviceConfig == null) {
- loadDisplayConfiguration();
+ loadDisplayDeviceConfig();
}
return mDisplayDeviceConfig;
}
- private void loadDisplayConfiguration() {
- Spline nitsToHal = null;
- Spline sysToNits = null;
-
- // Load the mapping from nits to HAL brightness range (display-device-config.xml)
+ private void loadDisplayDeviceConfig() {
+ // Load display device config
final Context context = getOverlayContext();
mDisplayDeviceConfig = DisplayDeviceConfig.create(context, mPhysicalDisplayId,
mIsDefaultDisplay);
@@ -427,33 +422,9 @@
return;
}
+ // Load brightness HWC quirk
mBacklightAdapter.setForceSurfaceControl(mDisplayDeviceConfig.hasQuirk(
DisplayDeviceConfig.QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC));
-
- final float[] halNits = mDisplayDeviceConfig.getNits();
- final float[] halBrightness = mDisplayDeviceConfig.getBrightness();
- if (halNits == null || halBrightness == null) {
- return;
- }
- nitsToHal = Spline.createSpline(halNits, halBrightness);
-
- // Load the mapping from system brightness range to nits (config.xml)
- final Resources res = context.getResources();
- final float[] sysNits = BrightnessMappingStrategy.getFloatArray(res.obtainTypedArray(
- com.android.internal.R.array.config_screenBrightnessNits));
- final int[] sysBrightness = res.getIntArray(
- com.android.internal.R.array.config_screenBrightnessBacklight);
- if (sysNits.length == 0 || sysBrightness.length != sysNits.length) {
- return;
- }
- final float[] sysBrightnessFloat = new float[sysBrightness.length];
- for (int i = 0; i < sysBrightness.length; i++) {
- sysBrightnessFloat[i] = sysBrightness[i];
- }
- sysToNits = Spline.createSpline(sysBrightnessFloat, sysNits);
-
- mNitsToHalBrightness = nitsToHal;
- mSystemBrightnessToNits = sysToNits;
}
private boolean updateStaticInfo(SurfaceControl.StaticDisplayInfo info) {
@@ -665,13 +636,11 @@
// The display is trusted since it is created by system.
mInfo.flags |= DisplayDeviceInfo.FLAG_TRUSTED;
+ mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN;
+ mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX;
if (mDisplayDeviceConfig != null) {
- mInfo.brightnessMinimum = mDisplayDeviceConfig.getBrightnessMinimum();
- mInfo.brightnessMaximum = mDisplayDeviceConfig.getBrightnessMaximum();
mInfo.brightnessDefault = mDisplayDeviceConfig.getBrightnessDefault();
} else {
- mInfo.brightnessMinimum = PowerManager.BRIGHTNESS_MIN;
- mInfo.brightnessMaximum = PowerManager.BRIGHTNESS_MAX;
mInfo.brightnessDefault = 0.5f;
}
}
@@ -718,7 +687,12 @@
setDisplayState(Display.STATE_ON);
currentState = Display.STATE_ON;
} else {
- return; // old state and new state is off
+ if (oldState == Display.STATE_UNKNOWN) {
+ // There's no guarantee about what the initial state is
+ // at startup, so we have to set it if previous was UNKNOWN.
+ setDisplayState(state);
+ }
+ return;
}
}
@@ -806,8 +780,8 @@
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
+ "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
try {
- brightness = displayBrightnessToHalBrightness(brightness);
- mBacklightAdapter.setBrightness(brightness);
+ float backlight = brightnessToBacklight(brightness);
+ mBacklightAdapter.setBacklight(backlight);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"ScreenBrightness",
BrightnessSynchronizer.brightnessFloatToInt(brightness));
@@ -816,35 +790,8 @@
}
}
- /**
- * Converts brightness range from the framework's brightness space to the
- * Hal brightness space if the HAL brightness space has been provided via
- * a display device configuration file.
- */
- private float displayBrightnessToHalBrightness(float brightness) {
- // TODO: b/171380847 - This needs to be deprecated. The nits-to-brightness
- // relationship should be specified in display-config OR config.xml, but not
- // both, and no nits-space conversion should be necessary.
- //
- // Only do a conversion if there exists a unique system brightness and a
- // unique HAL brightness-to-nits range defined.
- if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) {
- return brightness;
- }
-
- // Sys brightness in this conversion is always specified in the old 1-255
- // range, so convert that here before the translation.
- final float brightnessInt =
- BrightnessSynchronizer.brightnessFloatToIntRange(brightness);
-
- if (BrightnessSynchronizer.floatEquals(
- brightnessInt, PowerManager.BRIGHTNESS_OFF)) {
- return PowerManager.BRIGHTNESS_OFF_FLOAT;
- }
-
- final float nits = mSystemBrightnessToNits.interpolate(brightnessInt);
- final float halBrightness = mNitsToHalBrightness.interpolate(nits);
- return halBrightness;
+ private float brightnessToBacklight(float brightness) {
+ return getDisplayDeviceConfig().getBacklightFromBrightness(brightness);
}
};
}
@@ -1333,11 +1280,12 @@
}
}
- void setBrightness(float brightness) {
+ // Set backlight within min and max backlight values
+ void setBacklight(float backlight) {
if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
- mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, brightness);
+ mSurfaceControlProxy.setDisplayBrightness(mDisplayToken, backlight);
} else if (mBacklight != null) {
- mBacklight.setBrightness(brightness);
+ mBacklight.setBrightness(backlight);
}
}
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index a7f34ed..4c4c978 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -259,7 +259,7 @@
}
private void mayDisableSystemAudioAndARC(int address) {
- if (HdmiUtils.isEligibleAddressForDevice(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM, address)) {
+ if (!HdmiUtils.isEligibleAddressForDevice(HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM, address)) {
return;
}
diff --git a/services/core/java/com/android/server/input/InputShellCommand.java b/services/core/java/com/android/server/input/InputShellCommand.java
index d08980c..720be82 100644
--- a/services/core/java/com/android/server/input/InputShellCommand.java
+++ b/services/core/java/com/android/server/input/InputShellCommand.java
@@ -29,6 +29,7 @@
import android.view.ViewConfiguration;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -199,6 +200,8 @@
runRoll(inputSource, displayId);
} else if ("motionevent".equals(arg)) {
runMotionEvent(inputSource, displayId);
+ } else if ("keycombination".equals(arg)) {
+ runKeyCombination(inputSource, displayId);
} else {
handleDefaultCommands(arg);
}
@@ -224,7 +227,7 @@
out.println();
out.println("The commands and default sources are:");
out.println(" text <string> (Default: touchscreen)");
- out.println(" keyevent [--longpress] <key code number or name> ..."
+ out.println(" keyevent [--longpress|--doubletap] <key code number or name> ..."
+ " (Default: keyboard)");
out.println(" tap <x> <y> (Default: touchscreen)");
out.println(" swipe <x1> <y1> <x2> <y2> [duration(ms)]"
@@ -234,6 +237,8 @@
out.println(" press (Default: trackball)");
out.println(" roll <dx> <dy> (Default: trackball)");
out.println(" motionevent <DOWN|UP|MOVE|CANCEL> <x> <y> (Default: touchscreen)");
+ out.println(" keycombination <key code 1> <key code 2> ..."
+ + " (Default: keyboard)");
}
}
@@ -282,6 +287,14 @@
final boolean longpress = "--longpress".equals(arg);
if (longpress) {
arg = getNextArgRequired();
+ } else {
+ final boolean doubleTap = "--doubletap".equals(arg);
+ if (doubleTap) {
+ arg = getNextArgRequired();
+ final int keycode = KeyEvent.keyCodeFromString(arg);
+ sendKeyDoubleTap(inputSource, keycode, displayId);
+ return;
+ }
}
do {
@@ -292,22 +305,32 @@
private void sendKeyEvent(int inputSource, int keyCode, boolean longpress, int displayId) {
final long now = SystemClock.uptimeMillis();
- int repeatCount = 0;
- KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, repeatCount,
+ KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0 /* repeatCount */,
0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
inputSource);
event.setDisplayId(displayId);
injectKeyEvent(event);
if (longpress) {
- repeatCount++;
- injectKeyEvent(KeyEvent.changeTimeRepeat(event, now, repeatCount,
+ // Some long press behavior would check the event time, we set a new event time here.
+ final long nextEventTime = now + ViewConfiguration.getGlobalActionKeyTimeout();
+ injectKeyEvent(KeyEvent.changeTimeRepeat(event, nextEventTime, 1 /* repeatCount */,
KeyEvent.FLAG_LONG_PRESS));
}
injectKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
}
+ private void sendKeyDoubleTap(int inputSource, int keyCode, int displayId) {
+ sendKeyEvent(inputSource, keyCode, false, displayId);
+ try {
+ Thread.sleep(ViewConfiguration.getDoubleTapMinTime());
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ sendKeyEvent(inputSource, keyCode, false, displayId);
+ }
+
private void runTap(int inputSource, int displayId) {
inputSource = getSource(inputSource, InputDevice.SOURCE_TOUCHSCREEN);
sendTap(inputSource, Float.parseFloat(getNextArgRequired()),
@@ -440,4 +463,59 @@
final long now = SystemClock.uptimeMillis();
injectMotionEvent(inputSource, action, now, now, x, y, pressure, displayId);
}
+
+ private void runKeyCombination(int inputSource, int displayId) {
+ String arg = getNextArgRequired();
+ ArrayList<Integer> keyCodes = new ArrayList<>();
+
+ while (arg != null) {
+ final int keyCode = KeyEvent.keyCodeFromString(arg);
+ if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
+ throw new IllegalArgumentException("Unknown keycode: " + arg);
+ }
+ keyCodes.add(keyCode);
+ arg = getNextArg();
+ }
+
+ // At least 2 keys.
+ if (keyCodes.size() < 2) {
+ throw new IllegalArgumentException("keycombination requires at least 2 keycodes");
+ }
+
+ sendKeyCombination(inputSource, keyCodes, displayId);
+ }
+
+ private void injectKeyEventAsync(KeyEvent event) {
+ InputManager.getInstance().injectInputEvent(event,
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ }
+
+ private void sendKeyCombination(int inputSource, ArrayList<Integer> keyCodes, int displayId) {
+ final long now = SystemClock.uptimeMillis();
+ final int count = keyCodes.size();
+ final KeyEvent[] events = new KeyEvent[count];
+ for (int i = 0; i < count; i++) {
+ final KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCodes.get(i), 0,
+ 0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
+ inputSource);
+ event.setDisplayId(displayId);
+ events[i] = event;
+ }
+
+ for (KeyEvent event: events) {
+ // Use async inject so interceptKeyBeforeQueueing or interceptKeyBeforeDispatching could
+ // handle keys.
+ injectKeyEventAsync(event);
+ }
+
+ try {
+ Thread.sleep(ViewConfiguration.getTapTimeout());
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ for (KeyEvent event: events) {
+ injectKeyEventAsync(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
+ }
+ }
}
diff --git a/services/core/java/com/android/server/input/OWNERS b/services/core/java/com/android/server/input/OWNERS
index 0313a40..82c6ee1 100644
--- a/services/core/java/com/android/server/input/OWNERS
+++ b/services/core/java/com/android/server/input/OWNERS
@@ -1,2 +1,3 @@
+lzye@google.com
michaelwr@google.com
svv@google.com
diff --git a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
index 7b400b6..6ea4bd2 100644
--- a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
+++ b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
@@ -17,7 +17,6 @@
package com.android.server.location;
import android.annotation.Nullable;
-import android.content.ComponentName;
import android.content.Context;
import android.hardware.location.ActivityRecognitionHardware;
import android.hardware.location.IActivityRecognitionHardwareClient;
@@ -27,6 +26,7 @@
import android.util.Log;
import com.android.server.ServiceWatcher;
+import com.android.server.ServiceWatcher.BoundService;
/**
* Proxy class to bind GmsCore to the ActivityRecognitionHardware.
@@ -82,7 +82,7 @@
return resolves;
}
- private void onBind(IBinder binder, ComponentName service) throws RemoteException {
+ private void onBind(IBinder binder, BoundService service) throws RemoteException {
String descriptor = binder.getInterfaceDescriptor();
if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(descriptor)) {
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 1bf9da7..57e9fc9 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -63,6 +63,7 @@
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationManagerInternal;
+import android.location.LocationManagerInternal.OnProviderLocationTagsChangeListener;
import android.location.LocationProvider;
import android.location.LocationRequest;
import android.location.LocationTime;
@@ -82,6 +83,7 @@
import android.provider.Settings;
import android.stats.location.LocationStatsEnums;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.Log;
@@ -252,9 +254,12 @@
// @GuardedBy("mProviderManagers")
// hold lock for writes, no lock necessary for simple reads
- private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
+ final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
new CopyOnWriteArrayList<>();
+ @GuardedBy("mLock")
+ private @Nullable OnProviderLocationTagsChangeListener mOnProviderLocationTagsChangeListener;
+
LocationManagerService(Context context, Injector injector, LocationEventLog eventLog) {
mContext = context.createAttributionContext(ATTRIBUTION_TAG);
mInjector = injector;
@@ -284,7 +289,7 @@
}
@Nullable
- private LocationProviderManager getLocationProviderManager(String providerName) {
+ LocationProviderManager getLocationProviderManager(String providerName) {
if (providerName == null) {
return null;
}
@@ -319,8 +324,9 @@
Preconditions.checkState(getLocationProviderManager(manager.getName()) == null);
manager.startManager();
+ manager.setOnProviderLocationTagsChangeListener(
+ mOnProviderLocationTagsChangeListener);
if (realProvider != null) {
-
// custom logic wrapping all non-passive providers
if (manager != mPassiveManager) {
boolean enableStationaryThrottling = Settings.Global.getInt(
@@ -331,7 +337,6 @@
mInjector, realProvider, mEventLog);
}
}
-
manager.setRealProvider(realProvider);
}
mProviderManagers.add(manager);
@@ -456,8 +461,9 @@
.setPowerUsage(Integer.parseInt(fragments[8]))
.setAccuracy(Integer.parseInt(fragments[9]))
.build();
- getOrAddLocationProviderManager(name).setMockProvider(
- new MockLocationProvider(properties, CallerIdentity.fromContext(mContext)));
+ final LocationProviderManager manager = getOrAddLocationProviderManager(name);
+ manager.setMockProvider(new MockLocationProvider(properties,
+ CallerIdentity.fromContext(mContext), /*locationTags*/ null));
}
}
@@ -1147,15 +1153,16 @@
@Override
public void addTestProvider(String provider, ProviderProperties properties,
- String packageName, String attributionTag) {
+ List<String> locationTags, String packageName, String attributionTag) {
// unsafe is ok because app ops will verify the package name
CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag);
if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) {
return;
}
- getOrAddLocationProviderManager(provider).setMockProvider(
- new MockLocationProvider(properties, identity));
+ final LocationProviderManager manager = getOrAddLocationProviderManager(provider);
+ manager.setMockProvider(new MockLocationProvider(properties, identity,
+ (locationTags != null) ? new ArraySet<>(locationTags) : null));
}
@Override
@@ -1288,13 +1295,13 @@
ipw.println("Historical Aggregate Location Provider Data:");
ipw.increaseIndent();
- ArrayMap<String, ArrayMap<String, LocationEventLog.AggregateStats>> aggregateStats =
+ ArrayMap<String, ArrayMap<CallerIdentity, LocationEventLog.AggregateStats>> aggregateStats =
mEventLog.copyAggregateStats();
for (int i = 0; i < aggregateStats.size(); i++) {
ipw.print(aggregateStats.keyAt(i));
ipw.println(":");
ipw.increaseIndent();
- ArrayMap<String, LocationEventLog.AggregateStats> providerStats =
+ ArrayMap<CallerIdentity, LocationEventLog.AggregateStats> providerStats =
aggregateStats.valueAt(i);
for (int j = 0; j < providerStats.size(); j++) {
ipw.print(providerStats.keyAt(j));
@@ -1362,7 +1369,7 @@
if (provider != null && !provider.equals(manager.getName())) {
continue;
}
- if (identity.equalsIgnoringListenerId(manager.getIdentity())) {
+ if (identity.equals(manager.getIdentity())) {
return true;
}
}
@@ -1392,6 +1399,19 @@
return new LocationTime(location.getTime(), location.getElapsedRealtimeNanos());
}
+
+ @Override
+ public void setOnProviderLocationTagsChangeListener(
+ @Nullable OnProviderLocationTagsChangeListener listener) {
+ synchronized (mLock) {
+ mOnProviderLocationTagsChangeListener = listener;
+ final int providerCount = mProviderManagers.size();
+ for (int i = 0; i < providerCount; i++) {
+ final LocationProviderManager manager = mProviderManagers.get(i);
+ manager.setOnProviderLocationTagsChangeListener(listener);
+ }
+ }
+ }
}
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 f0dd8b5..21a9b04 100644
--- a/services/core/java/com/android/server/location/LocationShellCommand.java
+++ b/services/core/java/com/android/server/location/LocationShellCommand.java
@@ -75,8 +75,8 @@
case "add-test-provider": {
String provider = getNextArgRequired();
ProviderProperties properties = parseTestProviderProviderProperties();
- mService.addTestProvider(provider, properties, mContext.getOpPackageName(),
- mContext.getFeatureId());
+ mService.addTestProvider(provider, properties, /*locationTags*/ null,
+ mContext.getOpPackageName(), mContext.getFeatureId());
return 0;
}
case "remove-test-provider": {
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 81c1e45..dde45c4 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -295,7 +295,7 @@
};
SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
manager.addSensorPrivacyListener(
- SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE, listener);
+ SensorPrivacyManager.Sensors.MICROPHONE, listener);
}
}
@@ -1079,8 +1079,8 @@
*/
private void sendMicrophoneDisableSettingUpdate() {
SensorPrivacyManager manager = SensorPrivacyManager.getInstance(mContext);
- boolean disabled = manager.isIndividualSensorPrivacyEnabled(
- SensorPrivacyManager.INDIVIDUAL_SENSOR_MICROPHONE);
+ boolean disabled = manager.isSensorPrivacyEnabled(
+ SensorPrivacyManager.Sensors.MICROPHONE);
Log.d(TAG, "Mic Disabled Setting: " + disabled);
mContextHubWrapper.onMicrophoneDisableSettingChanged(disabled);
}
diff --git a/services/core/java/com/android/server/location/countrydetector/ComprehensiveCountryDetector.java b/services/core/java/com/android/server/location/countrydetector/ComprehensiveCountryDetector.java
index af3907e..dda502b 100644
--- a/services/core/java/com/android/server/location/countrydetector/ComprehensiveCountryDetector.java
+++ b/services/core/java/com/android/server/location/countrydetector/ComprehensiveCountryDetector.java
@@ -320,13 +320,15 @@
"(source: " + detectedCountry.getSource()
+ ", countryISO: " + detectedCountry.getCountryIso() + ")")
+ " isAirplaneModeOff()=" + isAirplaneModeOff()
+ + " isWifiOn()=" + isWifiOn()
+ " mListener=" + mListener
+ " isGeoCoderImplemnted()=" + isGeoCoderImplemented());
}
if (startLocationBasedDetection && (detectedCountry == null
|| detectedCountry.getSource() > Country.COUNTRY_SOURCE_LOCATION)
- && isAirplaneModeOff() && mListener != null && isGeoCoderImplemented()) {
+ && (isAirplaneModeOff() || isWifiOn()) && mListener != null
+ && isGeoCoderImplemented()) {
if (DEBUG) Slog.d(TAG, "run startLocationBasedDetector()");
// Start finding location when the source is less reliable than the
// location and the airplane mode is off (as geocoder will not
@@ -387,6 +389,11 @@
mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 0;
}
+ protected boolean isWifiOn() {
+ return Settings.Global.getInt(
+ mContext.getContentResolver(), Settings.Global.WIFI_ON, 0) != 0;
+ }
+
/**
* Notify the country change.
*/
diff --git a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
index dbfd0a5..29ce378 100644
--- a/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
+++ b/services/core/java/com/android/server/location/eventlog/LocationEventLog.java
@@ -64,16 +64,17 @@
private static final int EVENT_LOCATION_POWER_SAVE_MODE_CHANGE = 10;
@GuardedBy("mAggregateStats")
- private final ArrayMap<String, ArrayMap<String, AggregateStats>> mAggregateStats;
+ private final ArrayMap<String, ArrayMap<CallerIdentity, AggregateStats>> mAggregateStats;
public LocationEventLog() {
super(getLogSize());
mAggregateStats = new ArrayMap<>(4);
}
- public ArrayMap<String, ArrayMap<String, AggregateStats>> copyAggregateStats() {
+ /** Copies out all aggregated stats. */
+ public ArrayMap<String, ArrayMap<CallerIdentity, AggregateStats>> copyAggregateStats() {
synchronized (mAggregateStats) {
- ArrayMap<String, ArrayMap<String, AggregateStats>> copy = new ArrayMap<>(
+ ArrayMap<String, ArrayMap<CallerIdentity, AggregateStats>> copy = new ArrayMap<>(
mAggregateStats);
for (int i = 0; i < copy.size(); i++) {
copy.setValueAt(i, new ArrayMap<>(copy.valueAt(i)));
@@ -82,17 +83,18 @@
}
}
- private AggregateStats getAggregateStats(String provider, String packageName) {
+ private AggregateStats getAggregateStats(String provider, CallerIdentity identity) {
synchronized (mAggregateStats) {
- ArrayMap<String, AggregateStats> packageMap = mAggregateStats.get(provider);
+ ArrayMap<CallerIdentity, AggregateStats> packageMap = mAggregateStats.get(provider);
if (packageMap == null) {
packageMap = new ArrayMap<>(2);
mAggregateStats.put(provider, packageMap);
}
- AggregateStats stats = packageMap.get(packageName);
+ CallerIdentity stripped = identity.stripListenerId();
+ AggregateStats stats = packageMap.get(stripped);
if (stats == null) {
stats = new AggregateStats();
- packageMap.put(packageName, stats);
+ packageMap.put(stripped, stats);
}
return stats;
}
@@ -117,34 +119,33 @@
public void logProviderClientRegistered(String provider, CallerIdentity identity,
LocationRequest request) {
addLogEvent(EVENT_PROVIDER_REGISTER_CLIENT, provider, identity, request);
- getAggregateStats(provider, identity.getPackageName())
- .markRequestAdded(request.getIntervalMillis());
+ getAggregateStats(provider, identity).markRequestAdded(request.getIntervalMillis());
}
/** Logs a client unregistration for a location provider. */
public void logProviderClientUnregistered(String provider, CallerIdentity identity) {
addLogEvent(EVENT_PROVIDER_UNREGISTER_CLIENT, provider, identity);
- getAggregateStats(provider, identity.getPackageName()).markRequestRemoved();
+ getAggregateStats(provider, identity).markRequestRemoved();
}
/** Logs a client for a location provider entering the active state. */
public void logProviderClientActive(String provider, CallerIdentity identity) {
- getAggregateStats(provider, identity.getPackageName()).markRequestActive();
+ getAggregateStats(provider, identity).markRequestActive();
}
/** Logs a client for a location provider leaving the active state. */
public void logProviderClientInactive(String provider, CallerIdentity identity) {
- getAggregateStats(provider, identity.getPackageName()).markRequestInactive();
+ getAggregateStats(provider, identity).markRequestInactive();
}
/** Logs a client for a location provider entering the foreground state. */
public void logProviderClientForeground(String provider, CallerIdentity identity) {
- getAggregateStats(provider, identity.getPackageName()).markRequestForeground();
+ getAggregateStats(provider, identity).markRequestForeground();
}
/** Logs a client for a location provider leaving the foreground state. */
public void logProviderClientBackground(String provider, CallerIdentity identity) {
- getAggregateStats(provider, identity.getPackageName()).markRequestBackground();
+ getAggregateStats(provider, identity).markRequestBackground();
}
/** Logs a change to the provider request for a location provider. */
@@ -165,7 +166,7 @@
if (Build.IS_DEBUGGABLE || D) {
addLogEvent(EVENT_PROVIDER_DELIVER_LOCATION, provider, numLocations, identity);
}
- getAggregateStats(provider, identity.getPackageName()).markLocationDelivered();
+ getAggregateStats(provider, identity).markLocationDelivered();
}
/** Logs that a provider has entered or exited stationary throttling. */
@@ -218,7 +219,7 @@
protected final String mProvider;
- protected ProviderEvent(long timeDelta, String provider) {
+ ProviderEvent(long timeDelta, String provider) {
super(timeDelta);
mProvider = provider;
}
@@ -234,7 +235,7 @@
private final int mUserId;
private final boolean mEnabled;
- protected ProviderEnabledEvent(long timeDelta, String provider, int userId,
+ ProviderEnabledEvent(long timeDelta, String provider, int userId,
boolean enabled) {
super(timeDelta, provider);
mUserId = userId;
@@ -252,7 +253,7 @@
private final boolean mMocked;
- protected ProviderMockedEvent(long timeDelta, String provider, boolean mocked) {
+ ProviderMockedEvent(long timeDelta, String provider, boolean mocked) {
super(timeDelta, provider);
mMocked = mocked;
}
@@ -273,7 +274,7 @@
private final CallerIdentity mIdentity;
@Nullable private final LocationRequest mLocationRequest;
- private ProviderRegisterEvent(long timeDelta, String provider, boolean registered,
+ ProviderRegisterEvent(long timeDelta, String provider, boolean registered,
CallerIdentity identity, @Nullable LocationRequest locationRequest) {
super(timeDelta, provider);
mRegistered = registered;
@@ -296,7 +297,7 @@
private final ProviderRequest mRequest;
- private ProviderUpdateEvent(long timeDelta, String provider, ProviderRequest request) {
+ ProviderUpdateEvent(long timeDelta, String provider, ProviderRequest request) {
super(timeDelta, provider);
mRequest = request;
}
@@ -311,7 +312,7 @@
private final int mNumLocations;
- private ProviderReceiveLocationEvent(long timeDelta, String provider, int numLocations) {
+ ProviderReceiveLocationEvent(long timeDelta, String provider, int numLocations) {
super(timeDelta, provider);
mNumLocations = numLocations;
}
@@ -327,7 +328,7 @@
private final int mNumLocations;
@Nullable private final CallerIdentity mIdentity;
- private ProviderDeliverLocationEvent(long timeDelta, String provider, int numLocations,
+ ProviderDeliverLocationEvent(long timeDelta, String provider, int numLocations,
@Nullable CallerIdentity identity) {
super(timeDelta, provider);
mNumLocations = numLocations;
@@ -345,7 +346,7 @@
private final boolean mStationaryThrottled;
- private ProviderStationaryThrottledEvent(long timeDelta, String provider,
+ ProviderStationaryThrottledEvent(long timeDelta, String provider,
boolean stationaryThrottled) {
super(timeDelta, provider);
mStationaryThrottled = stationaryThrottled;
@@ -363,7 +364,7 @@
@LocationPowerSaveMode
private final int mLocationPowerSaveMode;
- private LocationPowerSaveModeEvent(long timeDelta,
+ LocationPowerSaveModeEvent(long timeDelta,
@LocationPowerSaveMode int locationPowerSaveMode) {
super(timeDelta);
mLocationPowerSaveMode = locationPowerSaveMode;
@@ -401,7 +402,7 @@
private final int mUserId;
private final boolean mEnabled;
- private LocationEnabledEvent(long timeDelta, int userId, boolean enabled) {
+ LocationEnabledEvent(long timeDelta, int userId, boolean enabled) {
super(timeDelta);
mUserId = userId;
mEnabled = enabled;
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index 9216a6b..29da177 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -371,7 +371,8 @@
public GnssLocationProvider(Context context, Injector injector, GnssNative gnssNative,
GnssMetrics gnssMetrics) {
- super(FgThread.getExecutor(), CallerIdentity.fromContext(context), PROPERTIES);
+ super(FgThread.getExecutor(), CallerIdentity.fromContext(context), PROPERTIES,
+ /*locationTags*/ null);
mContext = context;
mGnssNative = gnssNative;
diff --git a/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java b/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
index 4e0a0b8..9ff6e6b 100644
--- a/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/AbstractLocationProvider.java
@@ -29,6 +29,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.UnaryOperator;
@@ -67,7 +68,7 @@
* Default state value for a location provider that is disabled with no properties and an
* empty provider package list.
*/
- public static final State EMPTY_STATE = new State(false, null, null);
+ public static final State EMPTY_STATE = new State(false, null, null, null);
/**
* The provider's allowed state.
@@ -84,10 +85,14 @@
*/
@Nullable public final CallerIdentity identity;
- private State(boolean allowed, ProviderProperties properties, CallerIdentity identity) {
+ @Nullable public final Set<String> locationTags;
+
+ private State(boolean allowed, ProviderProperties properties, CallerIdentity identity,
+ Set<String> locationTags) {
this.allowed = allowed;
this.properties = properties;
this.identity = identity;
+ this.locationTags = locationTags;
}
/**
@@ -97,7 +102,7 @@
if (allowed == this.allowed) {
return this;
} else {
- return new State(allowed, properties, identity);
+ return new State(allowed, properties, identity, locationTags);
}
}
@@ -108,7 +113,7 @@
if (Objects.equals(properties, this.properties)) {
return this;
} else {
- return new State(allowed, properties, identity);
+ return new State(allowed, properties, identity, locationTags);
}
}
@@ -119,10 +124,22 @@
if (Objects.equals(identity, this.identity)) {
return this;
} else {
- return new State(allowed, properties, identity);
+ return new State(allowed, properties, identity, locationTags);
}
}
+ /**
+ * Returns a state the same as the current but with location tags set as specified.
+ */
+ public State withLocationTags(@Nullable Set<String> locationTags) {
+ if (Objects.equals(locationTags, this.locationTags)) {
+ return this;
+ } else {
+ return new State(allowed, properties, identity, locationTags);
+ }
+ }
+
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -133,12 +150,13 @@
}
State state = (State) o;
return allowed == state.allowed && properties == state.properties
- && Objects.equals(identity, state.identity);
+ && Objects.equals(identity, state.identity)
+ && Objects.equals(locationTags, state.locationTags);
}
@Override
public int hashCode() {
- return Objects.hash(allowed, properties, identity);
+ return Objects.hash(allowed, properties, identity, locationTags);
}
}
@@ -195,10 +213,14 @@
* An optional identity and properties may be provided to initialize the location provider.
*/
protected AbstractLocationProvider(Executor executor, @Nullable CallerIdentity identity,
- @Nullable ProviderProperties properties) {
+ @Nullable ProviderProperties properties, @Nullable Set<String> locationTags) {
+ Preconditions.checkArgument(identity == null || identity.getListenerId() == null);
mExecutor = executor;
mInternalState = new AtomicReference<>(new InternalState(null,
- State.EMPTY_STATE.withIdentity(identity).withProperties(properties)));
+ State.EMPTY_STATE
+ .withIdentity(identity)
+ .withProperties(properties).withLocationTags(locationTags))
+ );
mController = new Controller();
}
@@ -273,10 +295,18 @@
* Call this method to report a change in provider packages.
*/
protected void setIdentity(@Nullable CallerIdentity identity) {
+ Preconditions.checkArgument(identity == null || identity.getListenerId() == null);
setState(state -> state.withIdentity(identity));
}
/**
+ * Call this method to report a change in provider location tags.
+ */
+ protected void setLocationTags(@Nullable Set<String> locationTags) {
+ setState(state -> state.withLocationTags(locationTags));
+ }
+
+ /**
* Call this method to report a new location.
*/
protected void reportLocation(LocationResult locationResult) {
@@ -335,6 +365,8 @@
private boolean mStarted = false;
+ Controller() {}
+
@Override
public State setListener(@Nullable Listener listener) {
InternalState oldInternalState = mInternalState.getAndUpdate(
diff --git a/services/core/java/com/android/server/location/provider/DelegateLocationProvider.java b/services/core/java/com/android/server/location/provider/DelegateLocationProvider.java
index a3ec867..49f6e64 100644
--- a/services/core/java/com/android/server/location/provider/DelegateLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/DelegateLocationProvider.java
@@ -40,7 +40,7 @@
private boolean mInitialized = false;
DelegateLocationProvider(Executor executor, AbstractLocationProvider delegate) {
- super(executor, null, null);
+ super(executor, null, null, null);
mDelegate = delegate;
}
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 388b5a4..1ecf3ee 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -52,6 +52,8 @@
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationManagerInternal;
+import android.location.LocationManagerInternal.LocationTagInfo;
+import android.location.LocationManagerInternal.OnProviderLocationTagsChangeListener;
import android.location.LocationManagerInternal.ProviderEnabledListener;
import android.location.LocationRequest;
import android.location.LocationResult;
@@ -85,6 +87,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.location.LocationPermissions;
@@ -117,6 +120,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Predicate;
@@ -304,6 +308,7 @@
LocationTransport transport, @PermissionLevel int permissionLevel) {
super(Objects.requireNonNull(request), identity, transport);
+ Preconditions.checkArgument(identity.getListenerId() != null);
Preconditions.checkArgument(permissionLevel > PERMISSION_NONE);
Preconditions.checkArgument(!request.getWorkSource().isEmpty());
@@ -1287,6 +1292,9 @@
@GuardedBy("mLock")
private @Nullable OnAlarmListener mDelayedRegister;
+ @GuardedBy("mLock")
+ private @Nullable OnProviderLocationTagsChangeListener mOnLocationTagsChangeListener;
+
public LocationProviderManager(Context context, Injector injector, LocationEventLog eventLog,
String name, @Nullable PassiveLocationProviderManager passiveManager) {
mContext = context;
@@ -1447,6 +1455,19 @@
}
}
+ /**
+ * Registers a listener for the location tags of the provider.
+ *
+ * @param listener The listener
+ */
+ public void setOnProviderLocationTagsChangeListener(
+ @Nullable OnProviderLocationTagsChangeListener listener) {
+ Preconditions.checkArgument(mOnLocationTagsChangeListener == null || listener == null);
+ synchronized (mLock) {
+ mOnLocationTagsChangeListener = listener;
+ }
+ }
+
public void setMockProvider(@Nullable MockLocationProvider provider) {
synchronized (mLock) {
Preconditions.checkState(mState != STATE_STOPPED);
@@ -2243,6 +2264,27 @@
if (oldState.allowed != newState.allowed) {
onEnabledChanged(UserHandle.USER_ALL);
}
+
+ if (!Objects.equals(oldState.locationTags, newState.locationTags)) {
+ if (mOnLocationTagsChangeListener != null) {
+ if (oldState.identity != null) {
+ FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
+ OnProviderLocationTagsChangeListener::onLocationTagsChanged,
+ mOnLocationTagsChangeListener, new LocationTagInfo(
+ oldState.identity.getUid(), oldState.identity.getPackageName(),
+ Collections.emptySet())
+ ));
+ }
+ if (newState.identity != null) {
+ FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
+ OnProviderLocationTagsChangeListener::onLocationTagsChanged,
+ mOnLocationTagsChangeListener, new LocationTagInfo(
+ newState.identity.getUid(), newState.identity.getPackageName(),
+ newState.locationTags)
+ ));
+ }
+ }
+ }
}
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/location/provider/MockLocationProvider.java b/services/core/java/com/android/server/location/provider/MockLocationProvider.java
index 0d8f643..7660f56 100644
--- a/services/core/java/com/android/server/location/provider/MockLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/MockLocationProvider.java
@@ -28,6 +28,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Set;
/**
* A mock location provider used by LocationManagerService to implement test providers.
@@ -38,9 +39,10 @@
@Nullable private Location mLocation;
- public MockLocationProvider(ProviderProperties properties, CallerIdentity identity) {
+ public MockLocationProvider(ProviderProperties properties, CallerIdentity identity,
+ @Nullable Set<String> locationTags) {
// using a direct executor is ok because this class has no locks that could deadlock
- super(DIRECT_EXECUTOR, identity, properties);
+ super(DIRECT_EXECUTOR, identity, properties, locationTags);
}
/** Sets the allowed state of this mock provider. */
diff --git a/services/core/java/com/android/server/location/provider/MockableLocationProvider.java b/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
index cb7264e..4ffa9a5 100644
--- a/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/MockableLocationProvider.java
@@ -75,7 +75,7 @@
public MockableLocationProvider(Object ownerLock) {
// using a direct executor is acceptable because all inbound calls are delegated to the
// actual provider implementations which will use their own executors
- super(DIRECT_EXECUTOR, null, null);
+ super(DIRECT_EXECUTOR, null, null, null);
mOwnerLock = ownerLock;
mRequest = ProviderRequest.EMPTY_REQUEST;
}
diff --git a/services/core/java/com/android/server/location/provider/PassiveLocationProvider.java b/services/core/java/com/android/server/location/provider/PassiveLocationProvider.java
index a5758a3..ee9d35d 100644
--- a/services/core/java/com/android/server/location/provider/PassiveLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/PassiveLocationProvider.java
@@ -47,7 +47,8 @@
public PassiveLocationProvider(Context context) {
// using a direct executor is ok because this class has no locks that could deadlock
- super(DIRECT_EXECUTOR, CallerIdentity.fromContext(context), PROPERTIES);
+ super(DIRECT_EXECUTOR, CallerIdentity.fromContext(context), PROPERTIES,
+ /*locationTags*/ null);
setAllowed(true);
}
diff --git a/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java b/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
index 4c97f64..f00478a 100644
--- a/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
+++ b/services/core/java/com/android/server/location/provider/proxy/ProxyLocationProvider.java
@@ -18,6 +18,7 @@
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
@@ -32,10 +33,12 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.server.ServiceWatcher;
+import com.android.server.ServiceWatcher.BoundService;
import com.android.server.location.provider.AbstractLocationProvider;
import java.io.FileDescriptor;
@@ -49,6 +52,9 @@
*/
public class ProxyLocationProvider extends AbstractLocationProvider {
+ private static final String KEY_LOCATION_TAGS = "android:location_allow_listed_tags";
+ private static final String LOCATION_TAGS_SEPARATOR = ";";
+
/**
* Creates and registers this proxy. If no suitable service is available for the proxy, returns
* null.
@@ -84,7 +90,7 @@
int nonOverlayPackageResId) {
// safe to use direct executor since our locks are not acquired in a code path invoked by
// our owning provider
- super(DIRECT_EXECUTOR, null, null);
+ super(DIRECT_EXECUTOR, null, null, null);
mContext = context;
mServiceWatcher = new ServiceWatcher(context, action, this::onBind,
@@ -94,22 +100,34 @@
mRequest = ProviderRequest.EMPTY_REQUEST;
}
+ private void updateLocationTagInfo(@NonNull BoundService boundService) {
+ if (boundService.metadata != null) {
+ final String tagsList = boundService.metadata.getString(KEY_LOCATION_TAGS);
+ if (tagsList != null) {
+ final String[] tags = tagsList.split(LOCATION_TAGS_SEPARATOR);
+ setLocationTags(new ArraySet<>(tags));
+ }
+ }
+ }
+
private boolean checkServiceResolves() {
return mServiceWatcher.checkServiceResolves();
}
- private void onBind(IBinder binder, ComponentName service) throws RemoteException {
+ private void onBind(IBinder binder, BoundService boundService) throws RemoteException {
ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
synchronized (mLock) {
mProxy = new Proxy();
- mService = service;
+ mService = boundService.component;
provider.setLocationProviderManager(mProxy);
ProviderRequest request = mRequest;
if (!request.equals(ProviderRequest.EMPTY_REQUEST)) {
provider.setRequest(request);
}
+
+ updateLocationTagInfo(boundService);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index ecf4438..2b9dd2d 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -882,9 +882,10 @@
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
try {
+ // TODO: There shouldn't be a need to receive callback for all changes.
mActivityManager.registerUidObserver(mUidObserver,
ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE,
- NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE, "android");
+ ActivityManager.PROCESS_STATE_UNKNOWN, "android");
mNetworkManager.registerObserver(mAlertObserver);
} catch (RemoteException e) {
// ignored; both services live in system_server
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 160d2da..afb47e8 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -32,7 +32,7 @@
void onNotificationActionClick(int callingUid, int callingPid, String key, int actionIndex,
Notification.Action action, NotificationVisibility nv, boolean generatedByAssistant);
void onNotificationClear(int callingUid, int callingPid,
- String pkg, String tag, int id, int userId, String key,
+ String pkg, int userId, String key,
@NotificationStats.DismissalSurface int dismissalSurface,
@NotificationStats.DismissalSentiment int dismissalSentiment,
NotificationVisibility nv);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8b4c639..f8cb2e4 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1044,15 +1044,19 @@
@Override
public void onNotificationClear(int callingUid, int callingPid,
- String pkg, String tag, int id, int userId, String key,
+ String pkg, int userId, String key,
@NotificationStats.DismissalSurface int dismissalSurface,
@NotificationStats.DismissalSentiment int dismissalSentiment,
NotificationVisibility nv) {
+ String tag = null;
+ int id = 0;
synchronized (mNotificationLock) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r != null) {
r.recordDismissalSurface(dismissalSurface);
r.recordDismissalSentiment(dismissalSentiment);
+ tag = r.getSbn().getTag();
+ id = r.getSbn().getId();
}
}
cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
diff --git a/services/core/java/com/android/server/os/NativeTombstoneManager.java b/services/core/java/com/android/server/os/NativeTombstoneManager.java
index d95a725..9c4c510 100644
--- a/services/core/java/com/android/server/os/NativeTombstoneManager.java
+++ b/services/core/java/com/android/server/os/NativeTombstoneManager.java
@@ -425,7 +425,7 @@
}
}
stream.end(token);
-
+ break;
case (int) Tombstone.SELINUX_LABEL:
selinuxLabel = stream.readString(Tombstone.SELINUX_LABEL);
diff --git a/services/core/java/com/android/server/pm/DataLoaderManagerService.java b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
index 308e815..9a9b14c 100644
--- a/services/core/java/com/android/server/pm/DataLoaderManagerService.java
+++ b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
@@ -171,7 +171,7 @@
}
}
- private class DataLoaderServiceConnection implements ServiceConnection {
+ private class DataLoaderServiceConnection implements ServiceConnection, IBinder.DeathRecipient {
final int mId;
final IDataLoaderStatusListener mListener;
IDataLoader mDataLoader;
@@ -194,6 +194,13 @@
mContext.unbindService(this);
return;
}
+ try {
+ service.linkToDeath(this, /*flags=*/0);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to DataLoader's death: " + mId, e);
+ onBindingDied(className);
+ return;
+ }
callListener(IDataLoaderStatusListener.DATA_LOADER_BOUND);
}
@@ -218,6 +225,13 @@
destroy();
}
+ @Override
+ public void binderDied() {
+ Slog.i(TAG, "DataLoader " + mId + " died");
+ callListener(IDataLoaderStatusListener.DATA_LOADER_DESTROYED);
+ destroy();
+ }
+
IDataLoader getDataLoader() {
return mDataLoader;
}
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 051875c..349561d 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -215,7 +215,7 @@
searchResult.mOutcome == DEX_SEARCH_FOUND_SPLIT;
if (primaryOrSplit && !isUsedByOtherApps
- && !PLATFORM_PACKAGE_NAME.equals(searchResult.mOwningPackageName)) {
+ && !isPlatformPackage(searchResult.mOwningPackageName)) {
// If the dex file is the primary apk (or a split) and not isUsedByOtherApps
// do not record it. This case does not bring any new usable information
// and can be safely skipped.
@@ -232,15 +232,24 @@
}
String classLoaderContext = mapping.getValue();
+
+ // Overwrite the class loader context for system server (instead of merging it).
+ // We expect system server jars to only change contexts in between OTAs and to
+ // otherwise be stable.
+ // Instead of implementing a complex clear-context logic post OTA, it is much
+ // simpler to always override the context for system server. This way, the context
+ // will always be up to date and we will avoid merging which could lead to the
+ // the context being marked as variable and thus making dexopt non-optimal.
+ boolean overwriteCLC = isPlatformPackage(searchResult.mOwningPackageName);
+
if (classLoaderContext != null
&& VMRuntime.isValidClassLoaderContext(classLoaderContext)) {
// Record dex file usage. If the current usage is a new pattern (e.g. new
// secondary, or UsedByOtherApps), record will return true and we trigger an
// async write to disk to make sure we don't loose the data in case of a reboot.
-
if (mPackageDexUsage.record(searchResult.mOwningPackageName,
dexPath, loaderUserId, loaderIsa, primaryOrSplit,
- loadingAppInfo.packageName, classLoaderContext)) {
+ loadingAppInfo.packageName, classLoaderContext, overwriteCLC)) {
mPackageDexUsage.maybeWriteAsync();
}
}
@@ -474,7 +483,7 @@
* because they don't need to be compiled)..
*/
public boolean dexoptSecondaryDex(DexoptOptions options) {
- if (PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) {
+ if (isPlatformPackage(options.getPackageName())) {
// We could easily redirect to #dexoptSystemServer in this case. But there should be
// no-one calling this method directly for system server.
// As such we prefer to abort in this case.
@@ -534,7 +543,7 @@
* <p>PackageDexOptimizer.DEX_OPT_PERFORMED if all dexopt operations succeeded.
*/
public int dexoptSystemServer(DexoptOptions options) {
- if (!PLATFORM_PACKAGE_NAME.equals(options.getPackageName())) {
+ if (!isPlatformPackage(options.getPackageName())) {
Slog.wtf(TAG, "Non system server package used when trying to dexopt system server:"
+ options.getPackageName());
return PackageDexOptimizer.DEX_OPT_FAILED;
@@ -662,7 +671,7 @@
// Special handle system server files.
// We don't need an installd call because we have permissions to check if the file
// exists.
- if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
+ if (isPlatformPackage(packageName)) {
if (!Files.exists(Paths.get(dexPath))) {
if (DEBUG) {
Slog.w(TAG, "A dex file previously loaded by System Server does not exist "
@@ -739,7 +748,8 @@
boolean newUpdate = mPackageDexUsage.record(searchResult.mOwningPackageName,
dexPath, userId, isa, /*primaryOrSplit*/ false,
loadingPackage,
- PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT);
+ PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT,
+ /*overwriteCLC*/ false);
update |= newUpdate;
}
if (update) {
@@ -809,7 +819,7 @@
// Note: We don't have any way to detect which code paths are actually
// owned by system server. We can only assume that such paths are on
// system partitions.
- if (PLATFORM_PACKAGE_NAME.equals(loadingAppInfo.packageName)) {
+ if (isPlatformPackage(loadingAppInfo.packageName)) {
if (isSystemServerDexPathSupportedForOdex(dexPath)) {
// We record system server dex files as secondary dex files.
// The reason is that we only record the class loader context for secondary dex
@@ -842,6 +852,11 @@
return new DexSearchResult(null, DEX_SEARCH_NOT_FOUND);
}
+ /** Returns true if this is the platform package .*/
+ private static boolean isPlatformPackage(String packageName) {
+ return PLATFORM_PACKAGE_NAME.equals(packageName);
+ }
+
private static <K,V> V putIfAbsent(Map<K,V> map, K key, V newValue) {
V existingValue = map.putIfAbsent(key, newValue);
return existingValue == null ? newValue : existingValue;
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index 10760f5..3d63b75 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -111,17 +111,18 @@
* @param dexPath the path of the dex files being loaded
* @param ownerUserId the user id which runs the code loading the dex files
* @param loaderIsa the ISA of the app loading the dex files
- * @param isUsedByOtherApps whether or not this dex file was not loaded by its owning package
* @param primaryOrSplit whether or not the dex file is a primary/split dex. True indicates
* the file is either primary or a split. False indicates the file is secondary dex.
* @param loadingPackageName the package performing the load. Recorded only if it is different
* than {@param owningPackageName}.
+ * @param overwriteCLC if true, the class loader context will be overwritten instead of being
+ * merged
* @return true if the dex load constitutes new information, or false if this information
* has been seen before.
*/
/* package */ boolean record(String owningPackageName, String dexPath, int ownerUserId,
String loaderIsa, boolean primaryOrSplit,
- String loadingPackageName, String classLoaderContext) {
+ String loadingPackageName, String classLoaderContext, boolean overwriteCLC) {
if (!PackageManagerServiceUtils.checkISA(loaderIsa)) {
throw new IllegalArgumentException("loaderIsa " + loaderIsa + " is unsupported");
}
@@ -193,7 +194,7 @@
}
// Merge the information into the existing data.
// Returns true if there was an update.
- return existingData.merge(newData) || updateLoadingPackages;
+ return existingData.merge(newData, overwriteCLC) || updateLoadingPackages;
}
}
}
@@ -809,14 +810,16 @@
mLoadingPackages = new HashSet<>(other.mLoadingPackages);
}
- private boolean merge(DexUseInfo dexUseInfo) {
+ private boolean merge(DexUseInfo dexUseInfo, boolean overwriteCLC) {
boolean oldIsUsedByOtherApps = mIsUsedByOtherApps;
mIsUsedByOtherApps = mIsUsedByOtherApps || dexUseInfo.mIsUsedByOtherApps;
boolean updateIsas = mLoaderIsas.addAll(dexUseInfo.mLoaderIsas);
boolean updateLoadingPackages = mLoadingPackages.addAll(dexUseInfo.mLoadingPackages);
String oldClassLoaderContext = mClassLoaderContext;
- if (isUnsupportedContext(mClassLoaderContext)) {
+ if (overwriteCLC) {
+ mClassLoaderContext = dexUseInfo.mClassLoaderContext;
+ } else if (isUnsupportedContext(mClassLoaderContext)) {
mClassLoaderContext = dexUseInfo.mClassLoaderContext;
} else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
// We detected a context change.
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 71e53d9..7a936ec 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -68,15 +68,10 @@
import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManagerInternal;
-import android.app.role.RoleManager;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.PermissionGroupInfoFlags;
import android.content.pm.PackageManager.PermissionInfoFlags;
@@ -86,7 +81,6 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
-import android.content.pm.UserInfo;
import android.content.pm.parsing.component.ParsedPermission;
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.permission.SplitPermissionInfoParcelable;
@@ -401,105 +395,6 @@
new PermissionManagerServiceInternalImpl();
LocalServices.addService(PermissionManagerServiceInternal.class, localService);
LocalServices.addService(PermissionManagerInternal.class, localService);
-
- context.getMainThreadHandler().post(() -> context.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
- return;
- }
-
- try {
- fixBgMicCamera(context);
- } catch (Throwable t) {
- // Don't crash the system if this fails for any reason. Any intermediate state
- // this can leave the permissions in is okay and in the worst case the state is
- // the same as before the user rebooted.
- Log.e(LOG_TAG, "Unable to fix background permissions", t);
- }
- }
-
-
- private void fixBgMicCamera(Context context) {
- PackageManager pm = context.getPackageManager();
- for (UserInfo userInfo : context.getSystemService(UserManager.class).getUsers()) {
- UserHandle user = userInfo.getUserHandle();
- List<String> assistants = context.getSystemService(RoleManager.class)
- .getRoleHoldersAsUser(RoleManager.ROLE_ASSISTANT, user);
- List<PackageInfo> packages =
- pm.getInstalledPackagesAsUser(PackageManager.MATCH_SYSTEM_ONLY
- | PackageManager.GET_PERMISSIONS, user.getIdentifier());
- for (PackageInfo packageInfo : packages) {
- String[] requestedPermissions = packageInfo.requestedPermissions;
- if (requestedPermissions == null) {
- continue;
- }
- for (String permName : requestedPermissions) {
- String pkg = packageInfo.packageName;
- switch (permName) {
- case Manifest.permission.BACKGROUND_CAMERA:
- removeFromAllowlistsAndRevoke(pm, pkg, permName, user);
- break;
- case Manifest.permission.RECORD_BACKGROUND_AUDIO:
- if (assistants.contains(pkg)) {
- removeFromAllowlistsAndRevokeForAssistant(pm, pkg, permName,
- user);
- } else {
- removeFromAllowlistsAndRevoke(pm, pkg, permName, user);
- }
- break;
- }
- }
- }
- }
- }
-
- private void removeFromAllowlistsAndRevoke(PackageManager pm, String pkg,
- String permName, UserHandle user) {
- if ((pm.getPermissionFlags(permName, pkg, user)
- & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0) {
- Slog.i(LOG_TAG, "removing " + pkg + " " + permName + " from all allowlists");
- pm.removeWhitelistedRestrictedPermission(pkg, permName,
- FLAG_PERMISSION_WHITELIST_UPGRADE);
- pm.removeWhitelistedRestrictedPermission(pkg, permName,
- FLAG_PERMISSION_WHITELIST_SYSTEM);
- pm.removeWhitelistedRestrictedPermission(pkg, permName,
- FLAG_PERMISSION_WHITELIST_INSTALLER);
- pm.removeWhitelistedRestrictedPermission(pkg, permName,
- FLAG_PERMISSION_ALLOWLIST_ROLE);
- }
- if (pm.checkPermission(permName, pkg) == PackageManager.PERMISSION_GRANTED) {
- Slog.i(LOG_TAG, "revoking " + pkg + " " + permName);
- pm.revokeRuntimePermission(pkg, permName, user);
- }
- }
-
- private void removeFromAllowlistsAndRevokeForAssistant(PackageManager pm, String pkg,
- String permName, UserHandle user) {
- int anyNonRoleExempt =
- FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
- | FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
- | FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
-
- if ((pm.getPermissionFlags(permName, pkg, user) & anyNonRoleExempt) != 0) {
- Slog.i(LOG_TAG, "removing " + pkg + " " + permName
- + " from all allowlists except role");
- pm.removeWhitelistedRestrictedPermission(pkg, permName,
- FLAG_PERMISSION_WHITELIST_UPGRADE);
- pm.removeWhitelistedRestrictedPermission(pkg, permName,
- FLAG_PERMISSION_WHITELIST_SYSTEM);
- pm.removeWhitelistedRestrictedPermission(pkg, permName,
- FLAG_PERMISSION_WHITELIST_INSTALLER);
- }
- if ((pm.getPermissionFlags(permName, pkg, user)
- & FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT) == 0) {
- Slog.i(LOG_TAG, "adding " + pkg + " " + permName
- + " to role allowlist");
- pm.addWhitelistedRestrictedPermission(pkg, permName,
- FLAG_PERMISSION_ALLOWLIST_ROLE);
- }
- }
- }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)));
}
@Override
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
new file mode 100644
index 0000000..c965390
--- /dev/null
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -0,0 +1,151 @@
+/*
+ * 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.policy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal;
+import android.location.LocationManagerInternal;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.QuadFunction;
+import com.android.server.LocalServices;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This class defines policy for special behaviors around app ops.
+ */
+public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegate {
+ @NonNull
+ private final Object mLock = new Object();
+
+ /**
+ * The locking policy around the location tags is a bit special. Since we want to
+ * avoid grabbing the lock on every op note we are taking the approach where the
+ * read and write are being done via a thread-safe data structure such that the
+ * lookup/insert are single thread-safe calls. When we update the cached state we
+ * use a lock to ensure the update's lookup and store calls are done atomically,
+ * so multiple writers would not interleave. The tradeoff is we make is that the
+ * concurrent data structure would use boxing/unboxing of integers but this is
+ * preferred to locking.
+ */
+ @GuardedBy("mLock - writes only - see above")
+ @NonNull
+ private final ConcurrentHashMap<Integer, ArrayMap<String, ArraySet<String>>> mLocationTags =
+ new ConcurrentHashMap();
+
+ public AppOpsPolicy() {
+ final LocationManagerInternal locationManagerInternal = LocalServices.getService(
+ LocationManagerInternal.class);
+ locationManagerInternal.setOnProviderLocationTagsChangeListener((providerTagInfo) -> {
+ synchronized (mLock) {
+ final int uid = providerTagInfo.getUid();
+ // We make a copy of the per UID state to limit our mutation to one
+ // operation in the underlying concurrent data structure.
+ ArrayMap<String, ArraySet<String>> uidTags = mLocationTags.get(uid);
+ if (uidTags != null) {
+ uidTags = new ArrayMap<>(uidTags);
+ }
+
+ final String packageName = providerTagInfo.getPackageName();
+ ArraySet<String> packageTags = (uidTags != null) ? uidTags.get(packageName) : null;
+ if (packageTags != null) {
+ packageTags = new ArraySet<>(packageTags);
+ }
+
+ final Set<String> providerTags = providerTagInfo.getTags();
+ if (providerTags != null && !providerTags.isEmpty()) {
+ if (packageTags != null) {
+ packageTags.clear();
+ packageTags.addAll(providerTags);
+ } else {
+ packageTags = new ArraySet<>(providerTags);
+ }
+ if (uidTags == null) {
+ uidTags = new ArrayMap<>();
+ }
+ uidTags.put(packageName, packageTags);
+ mLocationTags.put(uid, uidTags);
+ } else if (uidTags != null) {
+ uidTags.remove(packageName);
+ if (!uidTags.isEmpty()) {
+ mLocationTags.put(uid, uidTags);
+ } else {
+ mLocationTags.remove(uid);
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public int checkOperation(int code, int uid, String packageName, boolean raw,
+ QuadFunction<Integer, Integer, String, Boolean, Integer> superImpl) {
+ return superImpl.apply(code, uid, packageName, raw);
+ }
+
+ @Override
+ public int checkAudioOperation(int code, int usage, int uid, String packageName,
+ QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) {
+ return superImpl.apply(code, usage, uid, packageName);
+ }
+
+ @Override
+ public int noteOperation(int code, int uid, @Nullable String packageName,
+ @Nullable String featureId, boolean shouldCollectAsyncNotedOp, @Nullable String message,
+ boolean shouldCollectMessage, @NonNull HeptFunction<Integer, Integer, String, String,
+ Boolean, String, Boolean, Integer> superImpl) {
+ if (isHandledOp(code)) {
+ // Only a single lookup from the underlying concurrent data structure
+ final ArrayMap<String, ArraySet<String>> uidTags = mLocationTags.get(uid);
+ if (uidTags != null) {
+ final ArraySet<String> packageTags = uidTags.get(packageName);
+ if (packageTags != null && packageTags.contains(featureId)) {
+ return superImpl.apply(resolveLocationOp(code), uid, packageName, featureId,
+ shouldCollectAsyncNotedOp, message, shouldCollectMessage);
+ }
+ }
+ }
+ return superImpl.apply(code, uid, packageName, featureId, shouldCollectAsyncNotedOp,
+ message, shouldCollectMessage);
+ }
+
+ private static boolean isHandledOp(int code) {
+ switch (code) {
+ case AppOpsManager.OP_FINE_LOCATION:
+ case AppOpsManager.OP_COARSE_LOCATION:
+ return true;
+ }
+ return false;
+ }
+
+ private static int resolveLocationOp(int code) {
+ switch (code) {
+ case AppOpsManager.OP_FINE_LOCATION:
+ return AppOpsManager.OP_FINE_LOCATION_SOURCE;
+ case AppOpsManager.OP_COARSE_LOCATION:
+ return AppOpsManager.OP_COARSE_LOCATION_SOURCE;
+ }
+ return code;
+ }
+}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 8c46445..bc11709 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1645,7 +1645,7 @@
}
// Called from native code.
- private void userActivityFromNative(long eventTime, int event, int flags) {
+ private void userActivityFromNative(long eventTime, int event, int displayId, int flags) {
userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);
}
diff --git a/services/core/java/com/android/server/speech/Android.bp b/services/core/java/com/android/server/speech/Android.bp
index 379b075..5605349 100644
--- a/services/core/java/com/android/server/speech/Android.bp
+++ b/services/core/java/com/android/server/speech/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "services.speech-sources",
srcs: ["java/**/*.java"],
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index a390df9..8ffbb0a 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -1336,7 +1336,7 @@
}
@Override
- public void onNotificationClear(String pkg, String tag, int id, int userId, String key,
+ public void onNotificationClear(String pkg, int userId, String key,
@NotificationStats.DismissalSurface int dismissalSurface,
@NotificationStats.DismissalSentiment int dismissalSentiment,
NotificationVisibility nv) {
@@ -1345,7 +1345,7 @@
final int callingPid = Binder.getCallingPid();
final long identity = Binder.clearCallingIdentity();
try {
- mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, tag, id, userId,
+ mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, userId,
key, dismissalSurface, dismissalSentiment, nv);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/timedetector/DeviceConfig.java b/services/core/java/com/android/server/timedetector/DeviceConfig.java
deleted file mode 100644
index 7b9ad0f..0000000
--- a/services/core/java/com/android/server/timedetector/DeviceConfig.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.timedetector;
-
-import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringDef;
-
-import java.time.Duration;
-import java.util.concurrent.Executor;
-
-/**
- * A helper class for reading / monitoring the {@link
- * android.provider.DeviceConfig#NAMESPACE_SYSTEM_TIME} namespace for server-configured flags.
- */
-public final class DeviceConfig {
-
- /**
- * An annotation used to indicate when a {@link
- * android.provider.DeviceConfig#NAMESPACE_SYSTEM_TIME} key is required.
- *
- * <p>Note that the com.android.geotz module deployment of the Offline LocationTimeZoneProvider
- * also shares the {@link android.provider.DeviceConfig#NAMESPACE_SYSTEM_TIME}, and uses the
- * prefix "geotz_" on all of its key strings.
- */
- @StringDef(prefix = "KEY_", value = {
- KEY_FORCE_LOCATION_TIME_ZONE_DETECTION_ENABLED,
- KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED_DEFAULT,
- KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
- KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
- KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
- })
- @interface DeviceConfigKey {}
-
- /**
- * The key to force location time zone detection on for a device. Only intended for use during
- * release testing with droidfooders. The user can still disable the feature by turning off the
- * master location switch, or disabling automatic time zone detection.
- */
- @DeviceConfigKey
- public static final String KEY_FORCE_LOCATION_TIME_ZONE_DETECTION_ENABLED =
- "force_location_time_zone_detection_enabled";
-
- /**
- * The key for the default value used to determine whether location time zone detection is
- * enabled when the user hasn't explicitly set it yet.
- */
- @DeviceConfigKey
- public static final String KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED_DEFAULT =
- "location_time_zone_detection_enabled_default";
-
- /**
- * The key for the minimum delay after location time zone detection has been enabled before the
- * location time zone manager can report it is uncertain about the time zone.
- */
- @DeviceConfigKey
- public static final String KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS =
- "location_time_zone_detection_uncertainty_delay_millis";
-
- /**
- * The key for the timeout passed to a location time zone provider that tells it how long it has
- * to provide an explicit first suggestion without being declared uncertain.
- */
- @DeviceConfigKey
- public static final String KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS =
- "ltpz_init_timeout_millis";
-
- /**
- * The key for the extra time added to {@link
- * #KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS} by the location time zone
- * manager before the location time zone provider will actually be declared uncertain.
- */
- @DeviceConfigKey
- public static final String KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS =
- "ltpz_init_timeout_fuzz_millis";
-
- /** Creates an instance. */
- public DeviceConfig() {}
-
- /** Adds a listener for the system_time namespace. */
- public void addListener(
- @NonNull Executor handlerExecutor, @NonNull Runnable listener) {
- android.provider.DeviceConfig.addOnPropertiesChangedListener(
- NAMESPACE_SYSTEM_TIME,
- handlerExecutor,
- properties -> listener.run());
- }
-
- /**
- * Returns a boolean value from {@link android.provider.DeviceConfig} from the system_time
- * namespace, or {@code defaultValue} if there is no explicit value set.
- */
- public boolean getBoolean(@DeviceConfigKey String key, boolean defaultValue) {
- return android.provider.DeviceConfig.getBoolean(NAMESPACE_SYSTEM_TIME, key, defaultValue);
- }
-
- /**
- * Returns a positive duration from {@link android.provider.DeviceConfig} from the system_time
- * namespace, or {@code defaultValue} if there is no explicit value set.
- */
- @Nullable
- public Duration getDurationFromMillis(
- @DeviceConfigKey String key, @Nullable Duration defaultValue) {
- long deviceConfigValue =
- android.provider.DeviceConfig.getLong(NAMESPACE_SYSTEM_TIME, key, -1);
- if (deviceConfigValue < 0) {
- return defaultValue;
- }
- return Duration.ofMillis(deviceConfigValue);
- }
-}
diff --git a/services/core/java/com/android/server/timedetector/ServerFlags.java b/services/core/java/com/android/server/timedetector/ServerFlags.java
new file mode 100644
index 0000000..8819b37
--- /dev/null
+++ b/services/core/java/com/android/server/timedetector/ServerFlags.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.timedetector;
+
+import static android.provider.DeviceConfig.NAMESPACE_SYSTEM_TIME;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.content.Context;
+import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.timezonedetector.ConfigurationChangeListener;
+import com.android.server.timezonedetector.ServiceConfigAccessor;
+
+import java.time.Duration;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * A helper class for reading / monitoring the {@link DeviceConfig#NAMESPACE_SYSTEM_TIME} namespace
+ * for server-configured flags.
+ */
+public final class ServerFlags {
+
+ private static final Optional<Boolean> OPTIONAL_TRUE = Optional.of(true);
+ private static final Optional<Boolean> OPTIONAL_FALSE = Optional.of(false);
+
+ /**
+ * An annotation used to indicate when a {@link DeviceConfig#NAMESPACE_SYSTEM_TIME} key is
+ * required.
+ *
+ * <p>Note that the com.android.geotz module deployment of the Offline LocationTimeZoneProvider
+ * also shares the {@link DeviceConfig#NAMESPACE_SYSTEM_TIME}, and uses the
+ * prefix "geotz_" on all of its key strings.
+ */
+ @StringDef(prefix = "KEY_", value = {
+ KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+ KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE,
+ KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE,
+ KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
+ KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
+ KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
+ KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
+ KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
+ })
+ @interface DeviceConfigKey {}
+
+ /**
+ * Controls whether the location time zone manager service will started. Only observed if
+ * the device build is configured to support location-based time zone detection. See
+ * {@link ServiceConfigAccessor#isGeoTimeZoneDetectionFeatureSupportedInConfig()} and {@link
+ * ServiceConfigAccessor#isGeoTimeZoneDetectionFeatureSupported()}.
+ */
+ @DeviceConfigKey
+ public static final String KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED =
+ "location_time_zone_detection_feature_supported";
+
+ /**
+ * The key for the server flag that can override the device config for whether the primary
+ * location time zone provider is enabled or disabled.
+ */
+ @DeviceConfigKey
+ public static final String KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE =
+ "primary_location_time_zone_provider_enabled_override";
+
+ /**
+ * The key for the server flag that can override the device config for whether the secondary
+ * location time zone provider is enabled or disabled.
+ */
+ @DeviceConfigKey
+ public static final String KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE =
+ "secondary_location_time_zone_provider_enabled_override";
+
+ /**
+ * The key for the minimum delay after location time zone detection has been enabled before the
+ * location time zone manager can report it is uncertain about the time zone.
+ */
+ @DeviceConfigKey
+ public static final String KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS =
+ "location_time_zone_detection_uncertainty_delay_millis";
+
+ /**
+ * The key for the timeout passed to a location time zone provider that tells it how long it has
+ * to provide an explicit first suggestion without being declared uncertain.
+ */
+ @DeviceConfigKey
+ public static final String KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS =
+ "ltpz_init_timeout_millis";
+
+ /**
+ * The key for the extra time added to {@link
+ * #KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS} by the location time zone
+ * manager before the location time zone provider will actually be declared uncertain.
+ */
+ @DeviceConfigKey
+ public static final String KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS =
+ "ltpz_init_timeout_fuzz_millis";
+
+ /**
+ * The key for the server flag that can override location time zone detection being enabled for
+ * a user. Only intended for use during release testing with droidfooders. The user can still
+ * disable the feature by turning off the master location switch, or by disabling automatic time
+ * zone detection.
+ */
+ @DeviceConfigKey
+ public static final String KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE =
+ "location_time_zone_detection_setting_enabled_override";
+
+ /**
+ * The key for the default value used to determine whether location time zone detection is
+ * enabled when the user hasn't explicitly set it yet.
+ */
+ @DeviceConfigKey
+ public static final String KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT =
+ "location_time_zone_detection_setting_enabled_default";
+
+ @GuardedBy("mListeners")
+ private final ArrayMap<ConfigurationChangeListener, Set<String>> mListeners = new ArrayMap<>();
+
+ private static final Object SLOCK = new Object();
+
+ @GuardedBy("SLOCK")
+ @Nullable
+ private static ServerFlags sInstance;
+
+ private ServerFlags(Context context) {
+ DeviceConfig.addOnPropertiesChangedListener(
+ NAMESPACE_SYSTEM_TIME,
+ context.getMainExecutor(),
+ this::handlePropertiesChanged);
+ }
+
+ /** Returns the singleton instance. */
+ public static ServerFlags getInstance(Context context) {
+ synchronized (SLOCK) {
+ if (sInstance == null) {
+ sInstance = new ServerFlags(context);
+ }
+ return sInstance;
+ }
+ }
+
+ private void handlePropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+ synchronized (mListeners) {
+ for (Map.Entry<ConfigurationChangeListener, Set<String>> listenerEntry
+ : mListeners.entrySet()) {
+ if (intersects(listenerEntry.getValue(), properties.getKeyset())) {
+ listenerEntry.getKey().onChange();
+ }
+ }
+ }
+ }
+
+ private static boolean intersects(@NonNull Set<String> one, @NonNull Set<String> two) {
+ for (String toFind : one) {
+ if (two.contains(toFind)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds a listener for the system_time namespace that will trigger if any of the specified keys
+ * change. Listener callbacks are delivered on the main looper thread.
+ *
+ * <p>Note: Only for use by long-lived objects like other singletons. There is deliberately no
+ * associated remove method.
+ */
+ public void addListener(@NonNull ConfigurationChangeListener listener,
+ @NonNull Set<String> keys) {
+ Objects.requireNonNull(listener);
+ Objects.requireNonNull(keys);
+
+ synchronized (mListeners) {
+ mListeners.put(listener, keys);
+ }
+ }
+
+ /**
+ * Returns an optional boolean value from {@link DeviceConfig} from the system_time
+ * namespace, returns {@link Optional#empty()} if there is no explicit value set.
+ */
+ @NonNull
+ public Optional<Boolean> getOptionalBoolean(@DeviceConfigKey String key) {
+ String value = DeviceConfig.getProperty(NAMESPACE_SYSTEM_TIME, key);
+ return parseOptionalBoolean(value);
+ }
+
+ @NonNull
+ private static Optional<Boolean> parseOptionalBoolean(@Nullable String value) {
+ if (value == null) {
+ return Optional.empty();
+ } else {
+ return Boolean.parseBoolean(value) ? OPTIONAL_TRUE : OPTIONAL_FALSE;
+ }
+ }
+
+ /**
+ * Returns a boolean value from {@link DeviceConfig} from the system_time
+ * namespace, or {@code defaultValue} if there is no explicit value set.
+ */
+ public boolean getBoolean(@DeviceConfigKey String key, boolean defaultValue) {
+ return DeviceConfig.getBoolean(NAMESPACE_SYSTEM_TIME, key, defaultValue);
+ }
+
+ /**
+ * Returns a positive duration from {@link DeviceConfig} from the system_time
+ * namespace, or {@code defaultValue} if there is no explicit value set.
+ */
+ @Nullable
+ public Duration getDurationFromMillis(
+ @DeviceConfigKey String key, @Nullable Duration defaultValue) {
+ long deviceConfigValue = DeviceConfig.getLong(NAMESPACE_SYSTEM_TIME, key, -1);
+ if (deviceConfigValue < 0) {
+ return defaultValue;
+ }
+ return Duration.ofMillis(deviceConfigValue);
+ }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationChangeListener.java b/services/core/java/com/android/server/timezonedetector/ConfigurationChangeListener.java
index 4c7b1f3..aa8ad37 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationChangeListener.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationChangeListener.java
@@ -17,10 +17,11 @@
package com.android.server.timezonedetector;
/**
- * A listener used to receive notification that time zone configuration has changed.
+ * A listener used to receive notification that configuration has / may have changed (depending on
+ * the usecase).
*/
@FunctionalInterface
public interface ConfigurationChangeListener {
- /** Called when the current user or a configuration value has changed. */
+ /** Called when the configuration may have changed. */
void onChange();
}
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
index 1f73977..3ae9d64 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
@@ -33,26 +33,27 @@
import java.util.Objects;
/**
- * Holds all configuration values that affect time zone behavior and some associated logic, e.g.
- * {@link #getAutoDetectionEnabledBehavior()}, {@link #getGeoDetectionEnabledBehavior()} and {@link
- * #createCapabilitiesAndConfig()}.
+ * Holds configuration values that affect user-facing time zone behavior and some associated logic.
+ * Some configuration is global, some is user scoped, but this class deliberately doesn't make a
+ * distinction for simplicity.
*/
public final class ConfigurationInternal {
- private final @UserIdInt int mUserId;
- private final boolean mUserConfigAllowed;
private final boolean mAutoDetectionSupported;
private final boolean mGeoDetectionSupported;
private final boolean mAutoDetectionEnabled;
+ private final @UserIdInt int mUserId;
+ private final boolean mUserConfigAllowed;
private final boolean mLocationEnabled;
private final boolean mGeoDetectionEnabled;
private ConfigurationInternal(Builder builder) {
- mUserId = builder.mUserId;
- mUserConfigAllowed = builder.mUserConfigAllowed;
mAutoDetectionSupported = builder.mAutoDetectionSupported;
mGeoDetectionSupported = builder.mGeoDetectionSupported;
mAutoDetectionEnabled = builder.mAutoDetectionEnabled;
+
+ mUserId = builder.mUserId;
+ mUserConfigAllowed = builder.mUserConfigAllowed;
mLocationEnabled = builder.mLocationEnabled;
mGeoDetectionEnabled = builder.mGeoDetectionEnabled;
// if mGeoDetectionSupported then mAutoDetectionSupported, i.e. mGeoDetectionSupported
@@ -60,22 +61,6 @@
Preconditions.checkState(mAutoDetectionSupported || !mGeoDetectionSupported);
}
- /** Returns the ID of the user this configuration is associated with. */
- public @UserIdInt int getUserId() {
- return mUserId;
- }
-
- /** Returns the handle of the user this configuration is associated with. */
- @NonNull
- public UserHandle getUserHandle() {
- return UserHandle.of(mUserId);
- }
-
- /** Returns true if the user allowed to modify time zone configuration. */
- public boolean isUserConfigAllowed() {
- return mUserConfigAllowed;
- }
-
/** Returns true if the device supports any form of auto time zone detection. */
public boolean isAutoDetectionSupported() {
return mAutoDetectionSupported;
@@ -98,6 +83,22 @@
return mAutoDetectionSupported && mAutoDetectionEnabled;
}
+ /** Returns the ID of the user this configuration is associated with. */
+ public @UserIdInt int getUserId() {
+ return mUserId;
+ }
+
+ /** Returns the handle of the user this configuration is associated with. */
+ @NonNull
+ public UserHandle getUserHandle() {
+ return UserHandle.of(mUserId);
+ }
+
+ /** Returns true if the user allowed to modify time zone configuration. */
+ public boolean isUserConfigAllowed() {
+ return mUserConfigAllowed;
+ }
+
/** Returns true if user's location can be used generally. */
public boolean isLocationEnabled() {
return mLocationEnabled;
@@ -283,7 +284,7 @@
/**
* Sets whether any form of automatic time zone detection is supported on this device.
*/
- public Builder setAutoDetectionSupported(boolean supported) {
+ public Builder setAutoDetectionFeatureSupported(boolean supported) {
mAutoDetectionSupported = supported;
return this;
}
@@ -291,7 +292,7 @@
/**
* Sets whether geolocation time zone detection is supported on this device.
*/
- public Builder setGeoDetectionSupported(boolean supported) {
+ public Builder setGeoDetectionFeatureSupported(boolean supported) {
mGeoDetectionSupported = supported;
return this;
}
diff --git a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
index f52b9b1..e3caae94 100644
--- a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
@@ -31,9 +31,7 @@
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.location.LocationManager;
-import android.net.ConnectivityManager;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -42,10 +40,9 @@
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
-import com.android.server.timedetector.DeviceConfig;
import java.util.Objects;
-import java.util.concurrent.Executor;
+import java.util.Optional;
/**
* The real implementation of {@link TimeZoneDetectorStrategyImpl.Environment}.
@@ -59,8 +56,7 @@
@NonNull private final Handler mHandler;
@NonNull private final ContentResolver mCr;
@NonNull private final UserManager mUserManager;
- @NonNull private final DeviceConfig mDeviceConfig;
- @NonNull private final boolean mGeoDetectionSupported;
+ @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
@NonNull private final LocationManager mLocationManager;
// @NonNull after setConfigChangeListener() is called.
@@ -68,17 +64,16 @@
private ConfigurationChangeListener mConfigChangeListener;
EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
- @NonNull DeviceConfig deviceConfig, boolean geoDetectionSupported) {
+ @NonNull ServiceConfigAccessor serviceConfigAccessor) {
mContext = Objects.requireNonNull(context);
mHandler = Objects.requireNonNull(handler);
- Executor handlerExecutor = new HandlerExecutor(mHandler);
mCr = context.getContentResolver();
mUserManager = context.getSystemService(UserManager.class);
mLocationManager = context.getSystemService(LocationManager.class);
- mDeviceConfig = deviceConfig;
- mGeoDetectionSupported = geoDetectionSupported;
+ mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
- // Wire up the change listeners. All invocations are performed on the mHandler thread.
+ // Wire up the config change listeners. All invocations are performed on the mHandler
+ // thread.
// Listen for the user changing / the user's location mode changing.
IntentFilter filter = new IntentFilter();
@@ -112,13 +107,6 @@
handleConfigChangeOnHandlerThread();
}
}, UserHandle.USER_ALL);
-
- // Add async callbacks for changes to server-side flags: some of the flags affect device /
- // user config. All changes can be treated like a config change. If flags that affect config
- // haven't changed then call will be a no-op.
- mDeviceConfig.addListener(
- handlerExecutor,
- this::handleConfigChangeOnHandlerThread);
}
private void handleConfigChangeOnHandlerThread() {
@@ -140,10 +128,12 @@
@Override
public ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
return new ConfigurationInternal.Builder(userId)
- .setUserConfigAllowed(isUserConfigAllowed(userId))
- .setAutoDetectionSupported(isAutoDetectionSupported())
- .setGeoDetectionSupported(isGeoDetectionSupported())
+ .setAutoDetectionFeatureSupported(
+ mServiceConfigAccessor.isAutoDetectionFeatureSupported())
+ .setGeoDetectionFeatureSupported(
+ mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported())
.setAutoDetectionEnabled(isAutoDetectionEnabled())
+ .setUserConfigAllowed(isUserConfigAllowed(userId))
.setLocationEnabled(isLocationEnabled(userId))
.setGeoDetectionEnabled(isGeoDetectionEnabled(userId))
.build();
@@ -186,18 +176,19 @@
// time zone detection: if we wrote it down then we'd set the value explicitly, which would
// prevent detecting "default" later. That might influence what happens on later releases
// that support new types of auto detection on the same hardware.
- if (isAutoDetectionSupported()) {
+ if (mServiceConfigAccessor.isAutoDetectionFeatureSupported()) {
final boolean autoDetectionEnabled = configuration.isAutoDetectionEnabled();
setAutoDetectionEnabledIfRequired(autoDetectionEnabled);
- // Avoid writing the geo detection enabled setting for devices that do not support geo
- // time zone detection: if we wrote it down then we'd set the value explicitly, which
- // would prevent detecting "default" later. That might influence what happens on later
- // releases that support geo detection on the same hardware.
- // Also avoid writing the geo detection enabled setting for devices that are currently
- // force-enabled: otherwise we might overwrite a droidfood user's real setting
- // permanently.
- if (isGeoDetectionSupported() && !isGeoDetectionForceEnabled()) {
+ // Avoid writing the geo detection enabled setting for devices with settings that
+ // are currently overridden by server flags: otherwise we might overwrite a droidfood
+ // user's real setting permanently.
+ // Also avoid writing the geo detection enabled setting for devices that do not support
+ // geo time zone detection: if we wrote it down then we'd set the value explicitly,
+ // which would prevent detecting "default" later. That might influence what happens on
+ // later releases that start to support geo detection on the same hardware.
+ if (!mServiceConfigAccessor.getGeoDetectionSettingEnabledOverride().isPresent()
+ && mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported()) {
final boolean geoTzDetectionEnabled = configuration.isGeoDetectionEnabled();
setGeoDetectionEnabledIfRequired(userId, geoTzDetectionEnabled);
}
@@ -209,14 +200,6 @@
return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME, userHandle);
}
- private boolean isAutoDetectionSupported() {
- return deviceHasTelephonyNetwork() || isGeoDetectionSupported();
- }
-
- private boolean isGeoDetectionSupported() {
- return mGeoDetectionSupported;
- }
-
private boolean isAutoDetectionEnabled() {
return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE, 1 /* default */) > 0;
}
@@ -237,24 +220,20 @@
private boolean isGeoDetectionEnabled(@UserIdInt int userId) {
// We may never use this, but it gives us a way to force location-based time zone detection
- // on for testers (where their other settings allow).
- boolean forceEnabled = isGeoDetectionForceEnabled();
- if (forceEnabled) {
- return true;
+ // on/off for testers (but only where their other settings would allow them to turn it on
+ // for themselves).
+ Optional<Boolean> override = mServiceConfigAccessor.getGeoDetectionSettingEnabledOverride();
+ if (override.isPresent()) {
+ return override.get();
}
- final boolean geoDetectionEnabledByDefault = mDeviceConfig.getBoolean(
- DeviceConfig.KEY_LOCATION_TIME_ZONE_DETECTION_ENABLED_DEFAULT, false);
+ final boolean geoDetectionEnabledByDefault =
+ mServiceConfigAccessor.isGeoDetectionEnabledForUsersByDefault();
return Settings.Secure.getIntForUser(mCr,
Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
(geoDetectionEnabledByDefault ? 1 : 0) /* defaultValue */, userId) != 0;
}
- private boolean isGeoDetectionForceEnabled() {
- return mDeviceConfig.getBoolean(
- DeviceConfig.KEY_FORCE_LOCATION_TIME_ZONE_DETECTION_ENABLED, false);
- }
-
private void setGeoDetectionEnabledIfRequired(@UserIdInt int userId, boolean enabled) {
// See comment in setAutoDetectionEnabledIfRequired. http://b/171953500
if (isGeoDetectionEnabled(userId) != enabled) {
@@ -262,10 +241,4 @@
enabled ? 1 : 0, userId);
}
}
-
- private boolean deviceHasTelephonyNetwork() {
- // TODO b/150583524 Avoid the use of a deprecated API.
- return mContext.getSystemService(ConnectivityManager.class)
- .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
- }
}
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
new file mode 100644
index 0000000..86c32f8
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.timezonedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.os.SystemProperties;
+import android.util.ArraySet;
+
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.timedetector.ServerFlags;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * A singleton that provides access to service configuration for time zone detection. This hides how
+ * configuration is split between static, compile-time config and dynamic, server-pushed flags. It
+ * provides a rudimentary mechanism to signal when values have changed.
+ */
+public final class ServiceConfigAccessor {
+
+ private static final Set<String> SERVER_FLAGS_KEYS_TO_WATCH = Collections.unmodifiableSet(
+ new ArraySet<>(new String[] {
+ ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+ ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
+ ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
+ ServerFlags.KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE,
+ ServerFlags.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE,
+ ServerFlags.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
+ ServerFlags.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
+ ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS
+ }));
+
+ // TODO(b/179488561): Put this back to 5 minutes when primary provider is fully implemented
+ private static final Duration DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT = Duration.ofMinutes(1);
+ // TODO(b/179488561): Put this back to 1 minute when primary provider is fully implemented
+ private static final Duration DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ =
+ Duration.ofSeconds(20);
+ private static final Duration DEFAULT_PROVIDER_UNCERTAINTY_DELAY = Duration.ofMinutes(5);
+
+ private static final Object SLOCK = new Object();
+
+ /** The singleton instance. Initialized once in {@link #getInstance(Context)}. */
+ @GuardedBy("SLOCK")
+ @Nullable
+ private static ServiceConfigAccessor sInstance;
+
+ @NonNull private final Context mContext;
+
+ /**
+ * An ultimate "feature switch" for location-based time zone detection. If this is
+ * {@code false}, the device cannot support the feature without a config change or a reboot:
+ * This affects what services are started on boot to minimize expense when the feature is not
+ * wanted.
+ */
+ private final boolean mGeoDetectionFeatureSupportedInConfig;
+
+ @NonNull private final ServerFlags mServerFlags;
+
+ private ServiceConfigAccessor(@NonNull Context context) {
+ mContext = Objects.requireNonNull(context);
+
+ // The config value is expected to be the main feature flag. Platform developers can also
+ // force enable the feature using a persistent system property. Because system properties
+ // can change, this value is cached and only changes on reboot.
+ mGeoDetectionFeatureSupportedInConfig = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection)
+ || SystemProperties.getBoolean(
+ "persist.sys.location_time_zone_detection_feature_supported", false);
+
+ mServerFlags = ServerFlags.getInstance(mContext);
+ }
+
+ /** Returns the singleton instance. */
+ public static ServiceConfigAccessor getInstance(Context context) {
+ synchronized (SLOCK) {
+ if (sInstance == null) {
+ sInstance = new ServiceConfigAccessor(context);
+ }
+ return sInstance;
+ }
+ }
+
+ /**
+ * Adds a listener that will be called server flags related to this class change. The callbacks
+ * are delivered on the main looper thread.
+ *
+ * <p>Note: Only for use by long-lived objects. There is deliberately no associated remove
+ * method.
+ */
+ public void addListener(@NonNull ConfigurationChangeListener listener) {
+ mServerFlags.addListener(listener, SERVER_FLAGS_KEYS_TO_WATCH);
+ }
+
+ /** Returns {@code true} if any form of automatic time zone detection is supported. */
+ public boolean isAutoDetectionFeatureSupported() {
+ return deviceHasTelephonyNetwork() || isGeoTimeZoneDetectionFeatureSupported();
+ }
+
+ private boolean deviceHasTelephonyNetwork() {
+ // TODO b/150583524 Avoid the use of a deprecated API.
+ return mContext.getSystemService(ConnectivityManager.class)
+ .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+ }
+
+ /**
+ * Returns {@code true} if the location-based time zone detection feature can be supported on
+ * this device at all according to config. When {@code false}, implies that various other
+ * location-based settings will be turned off or rendered meaningless. Typically {@link
+ * #isGeoTimeZoneDetectionFeatureSupported()} should be used instead.
+ */
+ public boolean isGeoTimeZoneDetectionFeatureSupportedInConfig() {
+ return mGeoDetectionFeatureSupportedInConfig;
+ }
+
+ /**
+ * Returns {@code true} if the location-based time zone detection feature is supported on the
+ * device. This can be used during feature testing on builds that are capable of location time
+ * zone detection to enable / disable the feature for some users.
+ */
+ public boolean isGeoTimeZoneDetectionFeatureSupported() {
+ return mGeoDetectionFeatureSupportedInConfig
+ && isGeoTimeZoneDetectionFeatureSupportedInternal();
+ }
+
+ private boolean isGeoTimeZoneDetectionFeatureSupportedInternal() {
+ final boolean defaultEnabled = true;
+ return mServerFlags.getBoolean(
+ ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+ defaultEnabled);
+ }
+
+ /**
+ * Returns {@code true} if the primary location time zone provider can be used.
+ */
+ public boolean isPrimaryLocationTimeZoneProviderEnabled() {
+ return getPrimaryLocationTimeZoneProviderEnabledOverride()
+ .orElse(isPrimaryLocationTimeZoneProviderEnabledInConfig());
+ }
+
+ private boolean isPrimaryLocationTimeZoneProviderEnabledInConfig() {
+ int providerEnabledConfigId = R.bool.config_enablePrimaryLocationTimeZoneProvider;
+ return getConfigBoolean(providerEnabledConfigId);
+ }
+
+ @NonNull
+ private Optional<Boolean> getPrimaryLocationTimeZoneProviderEnabledOverride() {
+ return mServerFlags.getOptionalBoolean(
+ ServerFlags.KEY_PRIMARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE);
+ }
+
+ /**
+ * Returns {@code true} if the secondary location time zone provider can be used.
+ */
+ public boolean isSecondaryLocationTimeZoneProviderEnabled() {
+ return getSecondaryLocationTimeZoneProviderEnabledOverride()
+ .orElse(isSecondaryLocationTimeZoneProviderEnabledInConfig());
+ }
+
+ private boolean isSecondaryLocationTimeZoneProviderEnabledInConfig() {
+ int providerEnabledConfigId = R.bool.config_enableSecondaryLocationTimeZoneProvider;
+ return getConfigBoolean(providerEnabledConfigId);
+ }
+
+ @NonNull
+ private Optional<Boolean> getSecondaryLocationTimeZoneProviderEnabledOverride() {
+ return mServerFlags.getOptionalBoolean(
+ ServerFlags.KEY_SECONDARY_LOCATION_TIME_ZONE_PROVIDER_ENABLED_OVERRIDE);
+ }
+
+ /**
+ * Returns whether location time zone detection is enabled for users when there's no setting
+ * value. Intended for use during feature release testing to "opt-in" users that haven't shown
+ * an explicit preference.
+ */
+ public boolean isGeoDetectionEnabledForUsersByDefault() {
+ return mServerFlags.getBoolean(
+ ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT, false);
+ }
+
+ /**
+ * Returns whether location time zone detection is force enabled/disabled for users. Intended
+ * for use during feature release testing to force a given state.
+ */
+ @NonNull
+ public Optional<Boolean> getGeoDetectionSettingEnabledOverride() {
+ return mServerFlags.getOptionalBoolean(
+ ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE);
+ }
+
+ /**
+ * Returns the time to send to a location time zone provider that informs it how long it has
+ * to return its first time zone suggestion.
+ */
+ @NonNull
+ public Duration getLocationTimeZoneProviderInitializationTimeout() {
+ return mServerFlags.getDurationFromMillis(
+ ServerFlags.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
+ DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT);
+ }
+
+ /**
+ * Returns the time added to {@link #getLocationTimeZoneProviderInitializationTimeout()} by the
+ * server before unilaterally declaring the provider is uncertain.
+ */
+ @NonNull
+ public Duration getLocationTimeZoneProviderInitializationTimeoutFuzz() {
+ return mServerFlags.getDurationFromMillis(
+ ServerFlags.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
+ DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ);
+ }
+
+ /**
+ * Returns the time after uncertainty is detected by providers before the location time zone
+ * manager makes a suggestion to the time zone detector.
+ */
+ @NonNull
+ public Duration getLocationTimeZoneUncertaintyDelay() {
+ return mServerFlags.getDurationFromMillis(
+ ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
+ DEFAULT_PROVIDER_UNCERTAINTY_DELAY);
+ }
+
+ private boolean getConfigBoolean(int providerEnabledConfigId) {
+ Resources resources = mContext.getResources();
+ return resources.getBoolean(providerEnabledConfigId);
+ }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
index 203a8a4..cd220b1 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
@@ -27,16 +27,21 @@
*/
public interface TimeZoneDetectorInternal extends Dumpable.Container {
- /** Adds a listener that will be invoked when time zone detection configuration is changed. */
- void addConfigurationListener(ConfigurationChangeListener listener);
+ /** Adds a listener that will be invoked when {@link ConfigurationInternal} may have changed. */
+ void addConfigurationListener(@NonNull ConfigurationChangeListener listener);
/**
* Removes a listener previously added via {@link
* #addConfigurationListener(ConfigurationChangeListener)}.
*/
- void removeConfigurationListener(ConfigurationChangeListener listener);
+ void removeConfigurationListener(@NonNull ConfigurationChangeListener listener);
- /** Returns the {@link ConfigurationInternal} for the current user. */
+ /**
+ * Returns a snapshot of the {@link ConfigurationInternal} for the current user. This is only a
+ * snapshot so callers must use {@link #addConfigurationListener(ConfigurationChangeListener)}
+ * to be notified when it changes.
+ */
+ @NonNull
ConfigurationInternal getCurrentUserConfigurationInternal();
/**
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index bd71ddf..c20400a 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -33,7 +33,6 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
-import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -62,27 +61,6 @@
static final String TAG = "time_zone_detector";
/**
- * A "feature switch" for location-based time zone detection. If this is {@code false}. It is
- * initialized and never refreshed; it affects what services are started on boot so consistency
- * is important.
- */
- @Nullable
- private static Boolean sGeoLocationTimeZoneDetectionSupported;
-
- /** Returns {@code true} if the location-based time zone detection feature is enabled. */
- public static boolean isGeoLocationTimeZoneDetectionSupported(Context context) {
- if (sGeoLocationTimeZoneDetectionSupported == null) {
- // The config value is expected to be the main switch. Platform developers can also
- // enable the feature using a persistent system property.
- sGeoLocationTimeZoneDetectionSupported = context.getResources().getBoolean(
- com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection)
- || SystemProperties.getBoolean(
- "persist.sys.location_time_zone_detection_feature_enabled", false);
- }
- return sGeoLocationTimeZoneDetectionSupported;
- }
-
- /**
* Handles the service lifecycle for {@link TimeZoneDetectorService} and
* {@link TimeZoneDetectorInternalImpl}.
*/
@@ -98,11 +76,10 @@
Context context = getContext();
Handler handler = FgThread.getHandler();
- boolean geolocationTimeZoneDetectionSupported =
- isGeoLocationTimeZoneDetectionSupported(context);
+ ServiceConfigAccessor serviceConfigAccessor =
+ ServiceConfigAccessor.getInstance(context);
TimeZoneDetectorStrategy timeZoneDetectorStrategy =
- TimeZoneDetectorStrategyImpl.create(
- context, handler, geolocationTimeZoneDetectionSupported);
+ TimeZoneDetectorStrategyImpl.create(context, handler, serviceConfigAccessor);
// Create and publish the local service for use by internal callers.
TimeZoneDetectorInternal internal =
@@ -330,7 +307,8 @@
boolean isGeoTimeZoneDetectionSupported() {
enforceManageTimeZoneDetectorPermission();
- return isGeoLocationTimeZoneDetectionSupported(mContext);
+ return ServiceConfigAccessor.getInstance(mContext)
+ .isGeoTimeZoneDetectionFeatureSupported();
}
@Override
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index 0b1d6d7..8266f12 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -75,17 +75,21 @@
public interface TimeZoneDetectorStrategy extends Dumpable, Dumpable.Container {
/**
- * Sets a listener that will be triggered whenever time zone detection configuration is
+ * Adds a listener that will be triggered whenever {@link ConfigurationInternal} may have
* changed.
*/
void addConfigChangeListener(@NonNull ConfigurationChangeListener listener);
- /** Returns the user's time zone configuration. */
+ /**
+ * Returns a snapshot of the configuration that controls time zone detector behavior for the
+ * specified user.
+ */
@NonNull
ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
/**
- * Returns the configuration that controls time zone detector behavior for the current user.
+ * Returns a snapshot of the configuration that controls time zone detector behavior for the
+ * current user.
*/
@NonNull
ConfigurationInternal getCurrentUserConfigurationInternal();
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index c464b74..d163a0e 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -38,7 +38,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.timedetector.DeviceConfig;
import java.util.ArrayList;
import java.util.List;
@@ -204,11 +203,9 @@
*/
public static TimeZoneDetectorStrategyImpl create(
@NonNull Context context, @NonNull Handler handler,
- boolean geoDetectionSupported) {
+ @NonNull ServiceConfigAccessor serviceConfigAccessor) {
- DeviceConfig deviceConfig = new DeviceConfig();
- EnvironmentImpl environment = new EnvironmentImpl(
- context, handler, deviceConfig, geoDetectionSupported);
+ Environment environment = new EnvironmentImpl(context, handler, serviceConfigAccessor);
return new TimeZoneDetectorStrategyImpl(environment);
}
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
index e463ee2..98e984d 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
@@ -19,9 +19,9 @@
import android.annotation.NonNull;
import com.android.server.LocalServices;
-import com.android.server.timedetector.DeviceConfig;
import com.android.server.timezonedetector.ConfigurationChangeListener;
import com.android.server.timezonedetector.ConfigurationInternal;
+import com.android.server.timezonedetector.ServiceConfigAccessor;
import com.android.server.timezonedetector.TimeZoneDetectorInternal;
import java.time.Duration;
@@ -33,28 +33,19 @@
*/
class ControllerEnvironmentImpl extends LocationTimeZoneProviderController.Environment {
- // TODO(b/179488561): Put this back to 5 minutes when primary provider is fully implemented
- private static final Duration DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT = Duration.ofMinutes(1);
- // TODO(b/179488561): Put this back to 5 minutes when primary provider is fully implemented
- private static final Duration DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ =
- Duration.ofSeconds(20);
- private static final Duration DEFAULT_PROVIDER_UNCERTAINTY_DELAY = Duration.ofMinutes(5);
-
@NonNull private final TimeZoneDetectorInternal mTimeZoneDetectorInternal;
- @NonNull private final LocationTimeZoneProviderController mController;
- @NonNull private final DeviceConfig mDeviceConfig;
+ @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
@NonNull private final ConfigurationChangeListener mConfigurationChangeListener;
ControllerEnvironmentImpl(@NonNull ThreadingDomain threadingDomain,
- @NonNull DeviceConfig deviceConfig,
+ @NonNull ServiceConfigAccessor serviceConfigAccessor,
@NonNull LocationTimeZoneProviderController controller) {
super(threadingDomain);
- mController = Objects.requireNonNull(controller);
- mDeviceConfig = Objects.requireNonNull(deviceConfig);
+ mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
mTimeZoneDetectorInternal = LocalServices.getService(TimeZoneDetectorInternal.class);
// Listen for configuration changes.
- mConfigurationChangeListener = () -> mThreadingDomain.post(mController::onConfigChanged);
+ mConfigurationChangeListener = () -> mThreadingDomain.post(controller::onConfigChanged);
mTimeZoneDetectorInternal.addConfigurationListener(mConfigurationChangeListener);
}
@@ -73,24 +64,18 @@
@Override
@NonNull
Duration getProviderInitializationTimeout() {
- return mDeviceConfig.getDurationFromMillis(
- DeviceConfig.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_MILLIS,
- DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT);
+ return mServiceConfigAccessor.getLocationTimeZoneProviderInitializationTimeout();
}
@Override
@NonNull
Duration getProviderInitializationTimeoutFuzz() {
- return mDeviceConfig.getDurationFromMillis(
- DeviceConfig.KEY_LOCATION_TIME_ZONE_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
- DEFAULT_PROVIDER_INITIALIZATION_TIMEOUT_FUZZ);
+ return mServiceConfigAccessor.getLocationTimeZoneProviderInitializationTimeoutFuzz();
}
@Override
@NonNull
Duration getUncertaintyDelay() {
- return mDeviceConfig.getDurationFromMillis(
- DeviceConfig.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
- DEFAULT_PROVIDER_UNCERTAINTY_DELAY);
+ return mServiceConfigAccessor.getLocationTimeZoneUncertaintyDelay();
}
}
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
index 364eaf8..0d1692a 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
@@ -21,11 +21,11 @@
import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_NONE;
import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_SIMULATED;
import static android.app.time.LocationTimeZoneManager.SECONDARY_PROVIDER_NAME;
+import static android.app.time.LocationTimeZoneManager.SERVICE_NAME;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.Resources;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -43,9 +43,8 @@
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.SystemService;
-import com.android.server.timedetector.DeviceConfig;
+import com.android.server.timezonedetector.ServiceConfigAccessor;
import com.android.server.timezonedetector.TimeZoneDetectorInternal;
-import com.android.server.timezonedetector.TimeZoneDetectorService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -96,28 +95,31 @@
private LocationTimeZoneManagerService mService;
+ @NonNull
+ private final ServiceConfigAccessor mServerConfigAccessor;
+
public Lifecycle(@NonNull Context context) {
super(Objects.requireNonNull(context));
+ mServerConfigAccessor = ServiceConfigAccessor.getInstance(context);
}
@Override
public void onStart() {
Context context = getContext();
- if (TimeZoneDetectorService.isGeoLocationTimeZoneDetectionSupported(context)) {
+ if (mServerConfigAccessor.isGeoTimeZoneDetectionFeatureSupportedInConfig()) {
mService = new LocationTimeZoneManagerService(context);
// The service currently exposes no LocalService or Binder API, but it extends
// Binder and is registered as a binder service so it can receive shell commands.
- publishBinderService("location_time_zone_manager", mService);
+ publishBinderService(SERVICE_NAME, mService);
} else {
- Slog.i(TAG, getClass() + " is disabled");
+ Slog.d(TAG, "Geo time zone detection feature is disabled in config");
}
}
@Override
- public void onBootPhase(int phase) {
- Context context = getContext();
- if (TimeZoneDetectorService.isGeoLocationTimeZoneDetectionSupported(context)) {
+ public void onBootPhase(@BootPhase int phase) {
+ if (mServerConfigAccessor.isGeoTimeZoneDetectionFeatureSupportedInConfig()) {
if (phase == PHASE_SYSTEM_SERVICES_READY) {
// The location service must be functioning after this boot phase.
mService.onSystemReady();
@@ -159,6 +161,9 @@
/** The shared lock from {@link #mThreadingDomain}. */
@NonNull private final Object mSharedLock;
+ @NonNull
+ private final ServiceConfigAccessor mServiceConfigAccessor;
+
// Lazily initialized. Can be null if the service has been stopped.
@GuardedBy("mSharedLock")
private ControllerImpl mLocationTimeZoneDetectorController;
@@ -180,24 +185,38 @@
mHandler = FgThread.getHandler();
mThreadingDomain = new HandlerThreadingDomain(mHandler);
mSharedLock = mThreadingDomain.getLockObject();
+ mServiceConfigAccessor = ServiceConfigAccessor.getInstance(mContext);
}
+ // According to the SystemService docs: All lifecycle methods are called from the system
+ // server's main looper thread.
void onSystemReady() {
- // Called on an arbitrary thread during initialization.
- synchronized (mSharedLock) {
- // TODO(b/152744911): LocationManagerService watches for packages disappearing. Need to
- // do anything here?
+ mServiceConfigAccessor.addListener(this::handleServiceConfigurationChangedOnMainThread);
+ }
- // TODO(b/152744911): LocationManagerService watches for foreground app changes. Need to
- // do anything here?
- // TODO(b/152744911): LocationManagerService watches screen state. Need to do anything
- // here?
+ private void handleServiceConfigurationChangedOnMainThread() {
+ // This method is called on the main thread, but service logic takes place on the threading
+ // domain thread, so we post the work there.
+
+ // The way all service-level configuration changes are handled is to just restart this
+ // service - this is simple and effective, and service configuration changes should be rare.
+ mThreadingDomain.post(this::restartIfRequiredOnDomainThread);
+ }
+
+ private void restartIfRequiredOnDomainThread() {
+ mThreadingDomain.assertCurrentThread();
+
+ synchronized (mSharedLock) {
+ // Stop and start the service, waiting until completion.
+ stopOnDomainThread();
+ startOnDomainThread();
}
}
+ // According to the SystemService docs: All lifecycle methods are called from the system
+ // server's main looper thread.
void onSystemThirdPartyAppsCanStart() {
- // Called on an arbitrary thread during initialization. We do not want to wait for
- // completion as it would delay boot.
+ // Do not wait for completion as it would delay boot.
final boolean waitForCompletion = false;
startInternal(waitForCompletion);
}
@@ -205,6 +224,9 @@
/**
* Starts the service during server initialization or during tests after a call to
* {@link #stop()}.
+ *
+ * <p>Because this method posts work to the {@code mThreadingDomain} thread and waits for
+ * completion, it cannot be called from the {@code mThreadingDomain} thread.
*/
void start() {
enforceManageTimeZoneDetectorPermission();
@@ -214,28 +236,17 @@
}
/**
- * Starts the service during server initialization or during tests after a call to
- * {@link #stop()}.
+ * Starts the service during server initialization, if the configuration changes or during tests
+ * after a call to {@link #stop()}.
*
* <p>To avoid tests needing to sleep, when {@code waitForCompletion} is {@code true}, this
* method will not return until all the system server components have started.
+ *
+ * <p>Because this method posts work to the {@code mThreadingDomain} thread, it cannot be
+ * called from the {@code mThreadingDomain} thread when {@code waitForCompletion} is true.
*/
private void startInternal(boolean waitForCompletion) {
- Runnable runnable = () -> {
- synchronized (mSharedLock) {
- if (mLocationTimeZoneDetectorController == null) {
- LocationTimeZoneProvider primary = createPrimaryProvider();
- LocationTimeZoneProvider secondary = createSecondaryProvider();
- mLocationTimeZoneDetectorController =
- new ControllerImpl(mThreadingDomain, primary, secondary);
- DeviceConfig deviceConfig = new DeviceConfig();
- mEnvironment = new ControllerEnvironmentImpl(
- mThreadingDomain, deviceConfig, mLocationTimeZoneDetectorController);
- ControllerCallbackImpl callback = new ControllerCallbackImpl(mThreadingDomain);
- mLocationTimeZoneDetectorController.initialize(mEnvironment, callback);
- }
- }
- };
+ Runnable runnable = this::startOnDomainThread;
if (waitForCompletion) {
mThreadingDomain.postAndWait(runnable, BLOCKING_OP_WAIT_DURATION_MILLIS);
} else {
@@ -243,11 +254,38 @@
}
}
+ private void startOnDomainThread() {
+ mThreadingDomain.assertCurrentThread();
+
+ synchronized (mSharedLock) {
+ if (!mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported()) {
+ debugLog("Not starting " + SERVICE_NAME + ": it is disabled in service config");
+ return;
+ }
+
+ if (mLocationTimeZoneDetectorController == null) {
+ LocationTimeZoneProvider primary = createPrimaryProvider();
+ LocationTimeZoneProvider secondary = createSecondaryProvider();
+
+ ControllerImpl controller =
+ new ControllerImpl(mThreadingDomain, primary, secondary);
+ ControllerEnvironmentImpl environment = new ControllerEnvironmentImpl(
+ mThreadingDomain, mServiceConfigAccessor, controller);
+ ControllerCallbackImpl callback = new ControllerCallbackImpl(mThreadingDomain);
+ controller.initialize(environment, callback);
+
+ mEnvironment = environment;
+ mLocationTimeZoneDetectorController = controller;
+ }
+ }
+ }
+
+ @NonNull
private LocationTimeZoneProvider createPrimaryProvider() {
LocationTimeZoneProviderProxy proxy;
if (isProviderInSimulationMode(PRIMARY_PROVIDER_NAME)) {
proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
- } else if (isProviderDisabled(PRIMARY_PROVIDER_NAME)) {
+ } else if (!isProviderEnabled(PRIMARY_PROVIDER_NAME)) {
proxy = new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
} else {
proxy = new RealLocationTimeZoneProviderProxy(
@@ -262,11 +300,12 @@
return new BinderLocationTimeZoneProvider(mThreadingDomain, PRIMARY_PROVIDER_NAME, proxy);
}
+ @NonNull
private LocationTimeZoneProvider createSecondaryProvider() {
LocationTimeZoneProviderProxy proxy;
if (isProviderInSimulationMode(SECONDARY_PROVIDER_NAME)) {
proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
- } else if (isProviderDisabled(SECONDARY_PROVIDER_NAME)) {
+ } else if (!isProviderEnabled(SECONDARY_PROVIDER_NAME)) {
proxy = new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
} else {
proxy = new RealLocationTimeZoneProviderProxy(
@@ -282,33 +321,27 @@
}
/** Used for bug triage and in tests to simulate provider events. */
- private boolean isProviderInSimulationMode(String providerName) {
+ private boolean isProviderInSimulationMode(@NonNull String providerName) {
return isProviderModeOverrideSet(providerName, PROVIDER_MODE_OVERRIDE_SIMULATED);
}
- /** Used for bug triage, tests and experiments to remove a provider. */
- private boolean isProviderDisabled(String providerName) {
- return !isProviderEnabledInConfig(providerName)
- || isProviderModeOverrideSet(providerName, PROVIDER_MODE_OVERRIDE_DISABLED);
- }
+ /** Used for bug triage, and by tests and experiments to remove a provider. */
+ private boolean isProviderEnabled(@NonNull String providerName) {
+ if (isProviderModeOverrideSet(providerName, PROVIDER_MODE_OVERRIDE_DISABLED)) {
+ return false;
+ }
- private boolean isProviderEnabledInConfig(String providerName) {
- int providerEnabledConfigId;
switch (providerName) {
case PRIMARY_PROVIDER_NAME: {
- providerEnabledConfigId = R.bool.config_enablePrimaryLocationTimeZoneProvider;
- break;
+ return mServiceConfigAccessor.isPrimaryLocationTimeZoneProviderEnabled();
}
case SECONDARY_PROVIDER_NAME: {
- providerEnabledConfigId = R.bool.config_enableSecondaryLocationTimeZoneProvider;
- break;
+ return mServiceConfigAccessor.isSecondaryLocationTimeZoneProviderEnabled();
}
default: {
throw new IllegalArgumentException(providerName);
}
}
- Resources resources = mContext.getResources();
- return resources.getBoolean(providerEnabledConfigId);
}
private boolean isProviderModeOverrideSet(@NonNull String providerName, @NonNull String mode) {
@@ -326,22 +359,29 @@
}
/**
- * Stops the service for tests. To avoid tests needing to sleep, this method will not return
- * until all the system server components have stopped.
+ * Stops the service for tests and other rare cases. To avoid tests needing to sleep, this
+ * method will not return until all the system server components have stopped.
+ *
+ * <p>Because this method posts work to the {@code mThreadingDomain} thread and waits it cannot
+ * be called from the {@code mThreadingDomain} thread.
*/
void stop() {
enforceManageTimeZoneDetectorPermission();
- mThreadingDomain.postAndWait(() -> {
- synchronized (mSharedLock) {
- if (mLocationTimeZoneDetectorController != null) {
- mLocationTimeZoneDetectorController.destroy();
- mLocationTimeZoneDetectorController = null;
- mEnvironment.destroy();
- mEnvironment = null;
- }
+ mThreadingDomain.postAndWait(this::stopOnDomainThread, BLOCKING_OP_WAIT_DURATION_MILLIS);
+ }
+
+ private void stopOnDomainThread() {
+ mThreadingDomain.assertCurrentThread();
+
+ synchronized (mSharedLock) {
+ if (mLocationTimeZoneDetectorController != null) {
+ mLocationTimeZoneDetectorController.destroy();
+ mLocationTimeZoneDetectorController = null;
+ mEnvironment.destroy();
+ mEnvironment = null;
}
- }, BLOCKING_OP_WAIT_DURATION_MILLIS);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
index b53150c..bdf4a70 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
@@ -21,6 +21,7 @@
import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_NONE;
import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_SIMULATED;
import static android.app.time.LocationTimeZoneManager.SECONDARY_PROVIDER_NAME;
+import static android.app.time.LocationTimeZoneManager.SERVICE_NAME;
import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_DUMP_STATE;
import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_RECORD_PROVIDER_STATES;
import static android.app.time.LocationTimeZoneManager.SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND;
@@ -102,7 +103,7 @@
@Override
public void onHelp() {
final PrintWriter pw = getOutPrintWriter();
- pw.println("Location Time Zone Manager (location_time_zone_manager) commands for tests:");
+ pw.printf("Location Time Zone Manager (%s) commands for tests:\n", SERVICE_NAME);
pw.println(" help");
pw.println(" Print this help text.");
pw.printf(" %s\n", SHELL_COMMAND_START);
diff --git a/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
index 38211ef..531c62c 100644
--- a/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/timezonedetector/location/RealLocationTimeZoneProviderProxy.java
@@ -25,7 +25,6 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -41,6 +40,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.server.ServiceWatcher;
+import com.android.server.ServiceWatcher.BoundService;
import java.util.Objects;
import java.util.function.Predicate;
@@ -123,7 +123,7 @@
return resolves;
}
- private void onBind(IBinder binder, ComponentName componentName) {
+ private void onBind(IBinder binder, BoundService boundService) {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
diff --git a/services/core/java/com/android/server/timezonedetector/location/TimeZoneProviderRequest.java b/services/core/java/com/android/server/timezonedetector/location/TimeZoneProviderRequest.java
index 1482031..e8386bc 100644
--- a/services/core/java/com/android/server/timezonedetector/location/TimeZoneProviderRequest.java
+++ b/services/core/java/com/android/server/timezonedetector/location/TimeZoneProviderRequest.java
@@ -63,8 +63,6 @@
return mSendUpdates;
}
- // TODO(b/152744911) - once there are a couple of implementations, decide whether this needs to
- // be passed to the TimeZoneProviderService and remove if it is not useful.
/**
* Returns the maximum time that the provider is allowed to initialize before it is expected to
* send an event of any sort. Only valid when {@link #sendUpdates()} is {@code true}. Failure to
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 9ee072e..06748a3 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -969,7 +969,7 @@
mGatewayStatusCallback.onGatewayConnectionError(
mConnectionConfig.getRequiredUnderlyingCapabilities(),
VCN_ERROR_CODE_INTERNAL_ERROR,
- "java.lang.RuntimeException",
+ RuntimeException.class.getName(),
"Received "
+ exception.getClass().getSimpleName()
+ " with message: "
@@ -991,11 +991,11 @@
} else if (exception instanceof IkeInternalException
&& exception.getCause() instanceof IOException) {
errorCode = VCN_ERROR_CODE_NETWORK_ERROR;
- exceptionClass = "java.io.IOException";
+ exceptionClass = IOException.class.getName();
exceptionMessage = exception.getCause().getMessage();
} else {
errorCode = VCN_ERROR_CODE_INTERNAL_ERROR;
- exceptionClass = "java.lang.RuntimeException";
+ exceptionClass = RuntimeException.class.getName();
exceptionMessage =
"Received "
+ exception.getClass().getSimpleName()
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5d3b9c1..dd9619a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -3624,7 +3624,7 @@
}
// Reset the last saved PiP snap fraction on removal.
- mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
+ mDisplayContent.mPinnedTaskControllerLocked.onActivityHidden(mActivityComponent);
mWmService.mEmbeddedWindowController.onActivityRemoved(this);
mRemovingFromDisplay = false;
}
@@ -4976,7 +4976,7 @@
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
mAppStopped = true;
// Reset the last saved PiP snap fraction on app stop.
- mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
+ mDisplayContent.mPinnedTaskControllerLocked.onActivityHidden(mActivityComponent);
destroySurfaces();
// Remove any starting window that was added for this app if they are still around.
removeStartingWindow();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b803fc3..af032c1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2095,10 +2095,14 @@
}
}
- /** @return the max ANR delay from all registered {@link AnrController} instances */
- public long getMaxAnrDelayMillis(ApplicationInfo info) {
+ /**
+ * @return the controller with the max ANR delay from all registered
+ * {@link AnrController} instances
+ */
+ @Nullable
+ public AnrController getAnrController(ApplicationInfo info) {
if (info == null || info.packageName == null) {
- return 0;
+ return null;
}
final ArrayList<AnrController> controllers;
@@ -2107,12 +2111,19 @@
}
final String packageName = info.packageName;
+ final int uid = info.uid;
long maxDelayMs = 0;
+ AnrController controllerWithMaxDelay = null;
+
for (AnrController controller : controllers) {
- maxDelayMs = Math.max(maxDelayMs, controller.getAnrDelayMillis(packageName, info.uid));
+ long delayMs = controller.getAnrDelayMillis(packageName, uid);
+ if (delayMs > 0 && delayMs > maxDelayMs) {
+ controllerWithMaxDelay = controller;
+ maxDelayMs = delayMs;
+ }
}
- maxDelayMs = Math.max(maxDelayMs, 0);
- return maxDelayMs;
+
+ return controllerWithMaxDelay;
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
index f505daa..a7312b3 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
@@ -67,39 +67,40 @@
* .setImeContainer(imeContainer)
* .setTaskDisplayAreas(rootTdaList);
*
- * // Build root hierarchy of front and rear DisplayAreaGroup.
- * RootDisplayArea frontRoot = new RootDisplayArea(wmService, "FrontRoot", FEATURE_FRONT_ROOT);
- * DisplayAreaPolicyBuilder.HierarchyBuilder frontGroupHierarchy =
- * new DisplayAreaPolicyBuilder.HierarchyBuilder(frontRoot)
+ * // Build root hierarchy of first and second DisplayAreaGroup.
+ * RootDisplayArea firstRoot = new RootDisplayArea(wmService, "FirstRoot", FEATURE_FIRST_ROOT);
+ * DisplayAreaPolicyBuilder.HierarchyBuilder firstGroupHierarchy =
+ * new DisplayAreaPolicyBuilder.HierarchyBuilder(firstRoot)
* // (Optional) .addFeature(...)
- * .setTaskDisplayAreas(frontTdaList);
+ * .setTaskDisplayAreas(firstTdaList);
*
- * RootDisplayArea rearRoot = new RootDisplayArea(wmService, "RearRoot", FEATURE_REAR_ROOT);
- * DisplayAreaPolicyBuilder.HierarchyBuilder rearGroupHierarchy =
- * new DisplayAreaPolicyBuilder.HierarchyBuilder(rearRoot)
+ * RootDisplayArea secondRoot = new RootDisplayArea(wmService, "SecondRoot",
+ * FEATURE_REAR_ROOT);
+ * DisplayAreaPolicyBuilder.HierarchyBuilder secondGroupHierarchy =
+ * new DisplayAreaPolicyBuilder.HierarchyBuilder(secondRoot)
* // (Optional) .addFeature(...)
- * .setTaskDisplayAreas(rearTdaList);
+ * .setTaskDisplayAreas(secondTdaList);
*
* // Define the function to select root for window to attach.
* BiFunction<WindowToken, Bundle, RootDisplayArea> selectRootForWindowFunc =
- * (windowToken, bundle) -> {
- * if (bundle == null) {
+ * (windowToken, options) -> {
+ * if (options == null) {
* return root;
* }
* // OEMs need to define the condition.
* if (...) {
- * return frontRoot;
+ * return firstRoot;
* }
* if (...) {
- * return rearRoot;
+ * return secondRoot;
* }
* return root;
* };
*
* return new DisplayAreaPolicyBuilder()
* .setRootHierarchy(rootHierarchy)
- * .addDisplayAreaGroupHierarchy(frontGroupHierarchy)
- * .addDisplayAreaGroupHierarchy(rearGroupHierarchy)
+ * .addDisplayAreaGroupHierarchy(firstGroupHierarchy)
+ * .addDisplayAreaGroupHierarchy(secondGroupHierarchy)
* .setSelectRootForWindowFunc(selectRootForWindowFunc)
* .build(wmService, content);
* </pre>
@@ -110,12 +111,12 @@
* - WindowedMagnification
* - DisplayArea.Tokens (Wallpapers can be attached here)
* - TaskDisplayArea
- * - RootDisplayArea (FrontRoot)
+ * - RootDisplayArea (FirstRoot)
* - DisplayArea.Tokens (Wallpapers can be attached here)
* - TaskDisplayArea
* - DisplayArea.Tokens (windows above Tasks up to IME can be attached here)
* - DisplayArea.Tokens (windows above IME can be attached here)
- * - RootDisplayArea (RearRoot)
+ * - RootDisplayArea (SecondRoot)
* - DisplayArea.Tokens (Wallpapers can be attached here)
* - TaskDisplayArea
* - DisplayArea.Tokens (windows above Tasks up to IME can be attached here)
@@ -133,14 +134,23 @@
* {@link RootDisplayArea}.
*/
class DisplayAreaPolicyBuilder {
+
+ /**
+ * Key to specify the {@link RootDisplayArea} to attach the window to. Should be used by the
+ * function passed in from {@link #setSelectRootForWindowFunc(BiFunction)}
+ */
+ static final String KEY_ROOT_DISPLAY_AREA_ID = "root_display_area_id";
+
@Nullable private HierarchyBuilder mRootHierarchyBuilder;
- private ArrayList<HierarchyBuilder> mDisplayAreaGroupHierarchyBuilders = new ArrayList<>();
+ private final ArrayList<HierarchyBuilder> mDisplayAreaGroupHierarchyBuilders =
+ new ArrayList<>();
/**
* When a window is created, the policy will use this function, which takes window type and
* options, to select the {@link RootDisplayArea} to place that window in. The selected root
* can be either the one of the {@link #mRootHierarchyBuilder} or the one of any of the
* {@link #mDisplayAreaGroupHierarchyBuilders}.
+ * @see DefaultSelectRootForWindowFunction as an example.
**/
@Nullable private BiFunction<Integer, Bundle, RootDisplayArea> mSelectRootForWindowFunc;
@@ -160,7 +170,10 @@
return this;
}
- /** The policy will use this function to find the root to place windows in. */
+ /**
+ * The policy will use this function to find the root to place windows in.
+ * @see DefaultSelectRootForWindowFunction as an example.
+ */
DisplayAreaPolicyBuilder setSelectRootForWindowFunc(
BiFunction<Integer, Bundle, RootDisplayArea> selectRootForWindowFunc) {
mSelectRootForWindowFunc = selectRootForWindowFunc;
@@ -169,7 +182,7 @@
/**
* Makes sure the setting meets the requirement:
- * 1. {@link mRootHierarchyBuilder} must be set.
+ * 1. {@link #mRootHierarchyBuilder} must be set.
* 2. {@link RootDisplayArea} and {@link TaskDisplayArea} must have unique ids.
* 3. {@link Feature} below the same {@link RootDisplayArea} must have unique ids.
* 4. There must be exactly one {@link HierarchyBuilder} that contains the IME container.
@@ -309,11 +322,57 @@
hierarchyBuilder.build();
displayAreaGroupRoots.add(hierarchyBuilder.mRoot);
}
+ // Use the default function if it is not specified otherwise.
+ if (mSelectRootForWindowFunc == null) {
+ mSelectRootForWindowFunc = new DefaultSelectRootForWindowFunction(
+ mRootHierarchyBuilder.mRoot, displayAreaGroupRoots);
+ }
return new Result(wmService, mRootHierarchyBuilder.mRoot, displayAreaGroupRoots,
mSelectRootForWindowFunc);
}
/**
+ * The default function to be used for finding {@link RootDisplayArea} for window to be attached
+ * to if there is no other function set through {@link #setSelectRootForWindowFunc(BiFunction)}.
+ *
+ * When a window is created with {@link Bundle} options, this function will select the
+ * {@link RootDisplayArea} based on the options. Returns {@link #mDisplayRoot} if there is no
+ * match found.
+ */
+ private static class DefaultSelectRootForWindowFunction implements
+ BiFunction<Integer, Bundle, RootDisplayArea> {
+ final RootDisplayArea mDisplayRoot;
+ final List<RootDisplayArea> mDisplayAreaGroupRoots;
+
+ DefaultSelectRootForWindowFunction(RootDisplayArea displayRoot,
+ List<RootDisplayArea> displayAreaGroupRoots) {
+ mDisplayRoot = displayRoot;
+ mDisplayAreaGroupRoots = Collections.unmodifiableList(displayAreaGroupRoots);
+ }
+
+ @Override
+ public RootDisplayArea apply(Integer windowType, Bundle options) {
+ if (mDisplayAreaGroupRoots.isEmpty()) {
+ return mDisplayRoot;
+ }
+
+ // Select the RootDisplayArea set in options.
+ if (options != null && options.containsKey(KEY_ROOT_DISPLAY_AREA_ID)) {
+ final int rootId = options.getInt(KEY_ROOT_DISPLAY_AREA_ID);
+ if (mDisplayRoot.mFeatureId == rootId) {
+ return mDisplayRoot;
+ }
+ for (int i = mDisplayAreaGroupRoots.size() - 1; i >= 0; i--) {
+ if (mDisplayAreaGroupRoots.get(i).mFeatureId == rootId) {
+ return mDisplayAreaGroupRoots.get(i);
+ }
+ }
+ }
+ return mDisplayRoot;
+ }
+ }
+
+ /**
* Builder to define {@link Feature} and {@link DisplayArea} hierarchy under a
* {@link RootDisplayArea}
*/
@@ -672,15 +731,10 @@
Result(WindowManagerService wmService, RootDisplayArea root,
List<RootDisplayArea> displayAreaGroupRoots,
- @Nullable BiFunction<Integer, Bundle, RootDisplayArea>
- selectRootForWindowFunc) {
+ BiFunction<Integer, Bundle, RootDisplayArea> selectRootForWindowFunc) {
super(wmService, root);
mDisplayAreaGroupRoots = Collections.unmodifiableList(displayAreaGroupRoots);
- mSelectRootForWindowFunc = selectRootForWindowFunc == null
- // Always return the highest level root of the logical display when the func is
- // not specified.
- ? (type, options) -> mRoot
- : selectRootForWindowFunc;
+ mSelectRootForWindowFunc = selectRootForWindowFunc;
// Cache the default TaskDisplayArea for quick access.
mDefaultTaskDisplayArea = mRoot.getItemFromTaskDisplayAreas(taskDisplayArea ->
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0143e70..eff4ea6 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -36,6 +36,7 @@
import static android.os.Build.VERSION_CODES.N;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
+import static android.util.RotationUtils.deltaRotation;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import static android.view.Display.FLAG_PRIVATE;
@@ -47,7 +48,6 @@
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
import static android.view.Surface.ROTATION_0;
-import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
@@ -150,7 +150,6 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.WindowConfiguration;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
@@ -158,10 +157,8 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Insets;
-import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Region.Op;
import android.hardware.HardwareBuffer;
@@ -206,6 +203,7 @@
import android.view.RemoteAnimationDefinition;
import android.view.RoundedCorners;
import android.view.Surface;
+import android.view.Surface.Rotation;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
@@ -449,8 +447,6 @@
/** Save allocating when calculating rects */
private final Rect mTmpRect = new Rect();
private final Rect mTmpRect2 = new Rect();
- private final RectF mTmpRectF = new RectF();
- private final Matrix mTmpMatrix = new Matrix();
private final Region mTmpRegion = new Region();
/** Used for handing back size of display */
@@ -461,8 +457,8 @@
/** Remove this display when animation on it has completed. */
private boolean mDeferredRemoval;
- final DockedStackDividerController mDividerControllerLocked;
- final PinnedStackController mPinnedStackControllerLocked;
+ final DockedTaskDividerController mDividerControllerLocked;
+ final PinnedTaskController mPinnedTaskControllerLocked;
final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
/** A collection of windows that provide tap exclude regions inside of them. */
@@ -1012,8 +1008,8 @@
mDisplayPolicy.systemReady();
}
mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius();
- mDividerControllerLocked = new DockedStackDividerController(this);
- mPinnedStackControllerLocked = new PinnedStackController(mWmService, this);
+ mDividerControllerLocked = new DockedTaskDividerController(this);
+ mPinnedTaskControllerLocked = new PinnedTaskController(mWmService, this);
final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession)
.setOpaque(true)
@@ -1289,7 +1285,7 @@
return mInsetsPolicy;
}
- @Surface.Rotation
+ @Rotation
int getRotation() {
return mDisplayRotation.getRotation();
}
@@ -1479,7 +1475,7 @@
* Returns a valid rotation if the activity can use different orientation than the display.
* Otherwise {@link #ROTATION_UNDEFINED}.
*/
- @Surface.Rotation
+ @Rotation
int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) {
if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) {
return ROTATION_UNDEFINED;
@@ -1567,7 +1563,7 @@
// has it own policy for bounds, the activity bounds based on parent is unknown.
return false;
}
- if (mPinnedStackControllerLocked.isPipActiveOrWindowingModeChanging()) {
+ if (mPinnedTaskControllerLocked.isPipActiveOrWindowingModeChanging()) {
// Use normal rotation animation because seamless PiP rotation is not supported yet.
return false;
}
@@ -1614,7 +1610,7 @@
* Sets the provided record to {@link #mFixedRotationLaunchingApp} if possible to apply fixed
* rotation transform to it and indicate that the display may be rotated after it is launched.
*/
- void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Surface.Rotation int rotation) {
+ void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Rotation int rotation) {
final WindowToken prevRotatedLaunchingApp = mFixedRotationLaunchingApp;
if (prevRotatedLaunchingApp == r
&& r.getWindowConfiguration().getRotation() == rotation) {
@@ -2296,12 +2292,12 @@
}
}
- DockedStackDividerController getDockedDividerController() {
+ DockedTaskDividerController getDockedDividerController() {
return mDividerControllerLocked;
}
- PinnedStackController getPinnedStackController() {
- return mPinnedStackControllerLocked;
+ PinnedTaskController getPinnedTaskController() {
+ return mPinnedTaskControllerLocked;
}
/**
@@ -2382,10 +2378,10 @@
* for bounds calculations.
*/
void preOnConfigurationChanged() {
- final PinnedStackController pinnedStackController = getPinnedStackController();
+ final PinnedTaskController pinnedTaskController = getPinnedTaskController();
- if (pinnedStackController != null) {
- getPinnedStackController().onConfigurationChanged();
+ if (pinnedTaskController != null) {
+ getPinnedTaskController().onConfigurationChanged();
}
}
@@ -2929,7 +2925,7 @@
final boolean imeVisible = imeWin != null && imeWin.isVisible()
&& imeWin.isDisplayed();
final int imeHeight = getInputMethodWindowVisibleHeight();
- mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
+ mPinnedTaskControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
}
int getInputMethodWindowVisibleHeight() {
@@ -2951,27 +2947,10 @@
forAllRootTasks(Task::prepareFreezingTaskBounds);
}
- void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
- getBounds(mTmpRect, newRotation);
- rotateBounds(mTmpRect, oldRotation, newRotation, bounds);
- }
-
- void rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds) {
- // Compute a transform matrix to undo the coordinate space transformation,
- // and present the window at the same physical position it previously occupied.
- final int deltaRotation = deltaRotation(newRotation, oldRotation);
- createRotationMatrix(
- deltaRotation, parentBounds.width(), parentBounds.height(), mTmpMatrix);
-
- mTmpRectF.set(bounds);
- mTmpMatrix.mapRect(mTmpRectF);
- mTmpRectF.round(bounds);
- }
-
- static int deltaRotation(int oldRotation, int newRotation) {
- int delta = newRotation - oldRotation;
- if (delta < 0) delta += 4;
- return delta;
+ void rotateBounds(@Rotation int oldRotation, @Rotation int newRotation, Rect inOutBounds) {
+ // Get display bounds on oldRotation as parent bounds for the rotation.
+ getBounds(mTmpRect, oldRotation);
+ RotationUtils.rotateBounds(inOutBounds, mTmpRect, oldRotation, newRotation);
}
public void setRotationAnimation(ScreenRotationAnimation screenRotationAnimation) {
@@ -2985,35 +2964,6 @@
return mScreenRotationAnimation;
}
- private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
- Matrix outMatrix) {
- // For rotations without Z-ordering we don't need the target rectangle's position.
- createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
- displayHeight, outMatrix);
- }
-
- static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
- float displayWidth, float displayHeight, Matrix outMatrix) {
- switch (rotation) {
- case ROTATION_0:
- outMatrix.reset();
- break;
- case ROTATION_270:
- outMatrix.setRotate(270, 0, 0);
- outMatrix.postTranslate(0, displayHeight);
- outMatrix.postTranslate(rectTop, 0);
- break;
- case ROTATION_180:
- outMatrix.reset();
- break;
- case ROTATION_90:
- outMatrix.setRotate(90, 0, 0);
- outMatrix.postTranslate(displayWidth, 0);
- outMatrix.postTranslate(-rectTop, rectLeft);
- break;
- }
- }
-
@Override
public void dumpDebug(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
@@ -3200,7 +3150,7 @@
}
pw.println();
- mPinnedStackControllerLocked.dump(prefix, pw);
+ mPinnedTaskControllerLocked.dump(prefix, pw);
pw.println();
mDisplayFrames.dump(prefix, pw);
@@ -3639,8 +3589,7 @@
}
private boolean isImeControlledByApp() {
- return mImeInputTarget != null && !WindowConfiguration.isSplitScreenWindowingMode(
- mImeInputTarget.getWindowingMode());
+ return mImeInputTarget != null && !mImeInputTarget.inMultiWindowMode();
}
boolean isImeAttachedToApp() {
@@ -4289,17 +4238,14 @@
out.set(left, top, left + width, top + height);
}
- private void getBounds(Rect out, int orientation) {
+ private void getBounds(Rect out, @Rotation int rotation) {
getBounds(out);
// Rotate the Rect if needed.
final int currentRotation = mDisplayInfo.rotation;
- final int rotationDelta = deltaRotation(currentRotation, orientation);
+ final int rotationDelta = deltaRotation(currentRotation, rotation);
if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
- createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
- mTmpRectF.set(out);
- mTmpMatrix.mapRect(mTmpRectF);
- mTmpRectF.round(out);
+ out.set(0, 0, out.height(), out.width());
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 5460e36..f64f04c 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -24,6 +24,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.util.RotationUtils.deltaRotation;
+import static android.util.RotationUtils.rotateBounds;
import static android.view.Display.TYPE_INTERNAL;
import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
@@ -1046,11 +1048,17 @@
return;
}
- // Get displayFrames bounds
- sTmpDisplayFrameBounds.set(0, 0, displayFrames.mDisplayWidth, displayFrames.mDisplayHeight);
+ // Get displayFrames bounds as it is on WindowState's rotation.
+ final int deltaRotation = deltaRotation(windowRotation, displayFrames.mRotation);
+ if (deltaRotation == Surface.ROTATION_90 || deltaRotation == Surface.ROTATION_270) {
+ sTmpDisplayFrameBounds.set(
+ 0, 0, displayFrames.mDisplayHeight, displayFrames.mDisplayWidth);
+ } else {
+ sTmpDisplayFrameBounds.set(
+ 0, 0, displayFrames.mDisplayWidth, displayFrames.mDisplayHeight);
+ }
// Rotate the WindowState's bounds based on the displayFrames rotation
- mDisplayContent.rotateBounds(sTmpDisplayFrameBounds, windowRotation,
- displayFrames.mRotation, outBounds);
+ rotateBounds(outBounds, sTmpDisplayFrameBounds, deltaRotation);
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index d5ded97..63cb38a 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.util.RotationUtils.deltaRotation;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
@@ -475,7 +476,7 @@
"Display id=%d rotation changed to %d from %d, lastOrientation=%d",
displayId, rotation, oldRotation, lastOrientation);
- if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) {
+ if (deltaRotation(oldRotation, rotation) != Surface.ROTATION_180) {
mDisplayContent.mWaitingForConfig = true;
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
similarity index 89%
rename from services/core/java/com/android/server/wm/DockedStackDividerController.java
rename to services/core/java/com/android/server/wm/DockedTaskDividerController.java
index de4bdaa..fb9d064 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedTaskDividerController.java
@@ -19,16 +19,16 @@
import android.graphics.Rect;
/**
- * Keeps information about the docked stack divider.
+ * Keeps information about the docked task divider.
*/
-public class DockedStackDividerController {
+public class DockedTaskDividerController {
private final DisplayContent mDisplayContent;
private boolean mResizing;
private final Rect mTouchRegion = new Rect();
- DockedStackDividerController(DisplayContent displayContent) {
+ DockedTaskDividerController(DisplayContent displayContent) {
mDisplayContent = displayContent;
}
@@ -58,6 +58,6 @@
private void resetDragResizingChangeReported() {
mDisplayContent.forAllWindows(WindowState::resetDragResizingChangeReported,
- true /* traverseTopToBottom */ );
+ true /* traverseTopToBottom */);
}
}
diff --git a/services/core/java/com/android/server/wm/FactoryErrorDialog.java b/services/core/java/com/android/server/wm/FactoryErrorDialog.java
index 88b5475..afdf1ee 100644
--- a/services/core/java/com/android/server/wm/FactoryErrorDialog.java
+++ b/services/core/java/com/android/server/wm/FactoryErrorDialog.java
@@ -41,6 +41,11 @@
public void onStop() {
}
+ @Override
+ protected void closeDialog() {
+ /* Do nothing */
+ }
+
private final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
throw new RuntimeException("Rebooting from failed factory test");
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java
similarity index 79%
rename from services/core/java/com/android/server/wm/PinnedStackController.java
rename to services/core/java/com/android/server/wm/PinnedTaskController.java
index 8fe2481..15e078b 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedTaskController.java
@@ -29,18 +29,18 @@
import android.util.Log;
import android.util.Slog;
import android.view.DisplayInfo;
-import android.view.IPinnedStackListener;
+import android.view.IPinnedTaskListener;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
- * Holds the common state of the pinned stack between the system and SystemUI. If SystemUI ever
+ * Holds the common state of the pinned task between the system and SystemUI. If SystemUI ever
* needs to be restarted, it will be notified with the last known state.
*
- * Changes to the pinned stack also flow through this controller, and generally, the system only
- * changes the pinned stack bounds through this controller in two ways:
+ * Changes to the pinned task also flow through this controller, and generally, the system only
+ * changes the pinned task bounds through this controller in two ways:
*
* 1) When first entering PiP: the controller returns the valid bounds given, taking aspect ratio
* and IME state into account.
@@ -49,18 +49,18 @@
* SystemUI adjustments (ie. expanded for menu, interaction, etc).
*
* Other changes in the system, including adjustment of IME, configuration change, and more are
- * handled by SystemUI (similar to the docked stack divider).
+ * handled by SystemUI (similar to the docked task divider).
*/
-class PinnedStackController {
+class PinnedTaskController {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedStackController" : TAG_WM;
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedTaskController" : TAG_WM;
private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
- private IPinnedStackListener mPinnedStackListener;
- private final PinnedStackListenerDeathHandler mPinnedStackListenerDeathHandler =
- new PinnedStackListenerDeathHandler();
+ private IPinnedTaskListener mPinnedTaskListener;
+ private final PinnedTaskListenerDeathHandler mPinnedTaskListenerDeathHandler =
+ new PinnedTaskListenerDeathHandler();
/** Whether the PiP is entering or leaving. */
private boolean mIsPipWindowingModeChanging;
@@ -72,7 +72,7 @@
private ArrayList<RemoteAction> mActions = new ArrayList<>();
private float mAspectRatio = -1f;
- // Used to calculate stack bounds across rotations
+ // Used to calculate task bounds across rotations
private final DisplayInfo mDisplayInfo = new DisplayInfo();
// The aspect ratio bounds of the PIP.
@@ -85,19 +85,19 @@
/**
* Handler for the case where the listener dies.
*/
- private class PinnedStackListenerDeathHandler implements IBinder.DeathRecipient {
+ private class PinnedTaskListenerDeathHandler implements IBinder.DeathRecipient {
@Override
public void binderDied() {
// Clean up the state if the listener dies
- if (mPinnedStackListener != null) {
- mPinnedStackListener.asBinder().unlinkToDeath(mPinnedStackListenerDeathHandler, 0);
+ if (mPinnedTaskListener != null) {
+ mPinnedTaskListener.asBinder().unlinkToDeath(mPinnedTaskListenerDeathHandler, 0);
}
- mPinnedStackListener = null;
+ mPinnedTaskListener = null;
}
}
- PinnedStackController(WindowManagerService service, DisplayContent displayContent) {
+ PinnedTaskController(WindowManagerService service, DisplayContent displayContent) {
mService = service;
mDisplayContent = displayContent;
mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
@@ -121,17 +121,17 @@
}
/**
- * Registers a pinned stack listener.
+ * Registers a pinned task listener.
*/
- void registerPinnedStackListener(IPinnedStackListener listener) {
+ void registerPinnedTaskListener(IPinnedTaskListener listener) {
try {
- listener.asBinder().linkToDeath(mPinnedStackListenerDeathHandler, 0);
- mPinnedStackListener = listener;
+ listener.asBinder().linkToDeath(mPinnedTaskListenerDeathHandler, 0);
+ mPinnedTaskListener = listener;
notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
notifyMovementBoundsChanged(false /* fromImeAdjustment */);
notifyActionsChanged(mActions);
} catch (RemoteException e) {
- Log.e(TAG, "Failed to register pinned stack listener", e);
+ Log.e(TAG, "Failed to register pinned task listener", e);
}
}
@@ -139,8 +139,8 @@
* @return whether the given {@param aspectRatio} is valid.
*/
public boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
- return Float.compare(mMinAspectRatio, aspectRatio) <= 0 &&
- Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
+ return Float.compare(mMinAspectRatio, aspectRatio) <= 0
+ && Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
}
/** Returns {@code true} if the PiP is on screen or is changing windowing mode. */
@@ -152,7 +152,7 @@
return pinnedTask != null && pinnedTask.hasChild();
}
- /** Sets whether a visible stack is changing from or to pinned mode. */
+ /** Sets whether a visible task is changing from or to pinned mode. */
void setPipWindowingModeChanging(boolean isPipWindowingModeChanging) {
mIsPipWindowingModeChanging = isPipWindowingModeChanging;
}
@@ -162,9 +162,9 @@
* so that the default bounds will be returned for the next session.
*/
void onActivityHidden(ComponentName componentName) {
- if (mPinnedStackListener == null) return;
+ if (mPinnedTaskListener == null) return;
try {
- mPinnedStackListener.onActivityHidden(componentName);
+ mPinnedTaskListener.onActivityHidden(componentName);
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering reset reentry fraction event.", e);
}
@@ -223,9 +223,9 @@
* Notifies listeners that the PIP needs to be adjusted for the IME.
*/
private void notifyImeVisibilityChanged(boolean imeVisible, int imeHeight) {
- if (mPinnedStackListener != null) {
+ if (mPinnedTaskListener != null) {
try {
- mPinnedStackListener.onImeVisibilityChanged(imeVisible, imeHeight);
+ mPinnedTaskListener.onImeVisibilityChanged(imeVisible, imeHeight);
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering bounds changed event.", e);
}
@@ -233,9 +233,9 @@
}
private void notifyAspectRatioChanged(float aspectRatio) {
- if (mPinnedStackListener == null) return;
+ if (mPinnedTaskListener == null) return;
try {
- mPinnedStackListener.onAspectRatioChanged(aspectRatio);
+ mPinnedTaskListener.onAspectRatioChanged(aspectRatio);
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering aspect ratio changed event.", e);
}
@@ -245,9 +245,9 @@
* Notifies listeners that the PIP actions have changed.
*/
private void notifyActionsChanged(List<RemoteAction> actions) {
- if (mPinnedStackListener != null) {
+ if (mPinnedTaskListener != null) {
try {
- mPinnedStackListener.onActionsChanged(new ParceledListSlice(actions));
+ mPinnedTaskListener.onActionsChanged(new ParceledListSlice(actions));
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering actions changed event.", e);
}
@@ -259,11 +259,11 @@
*/
private void notifyMovementBoundsChanged(boolean fromImeAdjustment) {
synchronized (mService.mGlobalLock) {
- if (mPinnedStackListener == null) {
+ if (mPinnedTaskListener == null) {
return;
}
try {
- mPinnedStackListener.onMovementBoundsChanged(fromImeAdjustment);
+ mPinnedTaskListener.onMovementBoundsChanged(fromImeAdjustment);
} catch (RemoteException e) {
Slog.e(TAG_WM, "Error delivering actions changed event.", e);
}
@@ -271,7 +271,7 @@
}
void dump(String prefix, PrintWriter pw) {
- pw.println(prefix + "PinnedStackController");
+ pw.println(prefix + "PinnedTaskController");
pw.println(prefix + " mIsImeShowing=" + mIsImeShowing);
pw.println(prefix + " mImeHeight=" + mImeHeight);
pw.println(prefix + " mAspectRatio=" + mAspectRatio);
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 533c82e..95a4f69e 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.util.RotationUtils.deltaRotation;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
@@ -174,7 +175,7 @@
// apply rotation animation because there should be a top app shown as rotated. So the
// specified original rotation customizes the direction of animation to have better look
// when restoring the rotated app to the same rotation as current display.
- final int delta = DisplayContent.deltaRotation(originalRotation, realOriginalRotation);
+ final int delta = deltaRotation(originalRotation, realOriginalRotation);
final boolean flipped = delta == Surface.ROTATION_90 || delta == Surface.ROTATION_270;
mOriginalWidth = flipped ? originalHeight : originalWidth;
mOriginalHeight = flipped ? originalWidth : originalHeight;
@@ -330,7 +331,7 @@
// Compute the transformation matrix that must be applied
// to the snapshot to make it stay in the same original position
// with the current screen rotation.
- int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0);
+ int delta = deltaRotation(rotation, Surface.ROTATION_0);
RotationAnimationUtils.createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
setRotationTransform(t, mSnapshotInitialMatrix);
@@ -352,8 +353,7 @@
mStarted = true;
// Figure out how the screen has moved from the original rotation.
- int delta = DisplayContent.deltaRotation(mCurRotation, mOriginalRotation);
-
+ int delta = deltaRotation(mCurRotation, mOriginalRotation);
final boolean customAnim;
if (exitAnim != 0 && enterAnim != 0) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index d60b6e0..29c7ff1 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2267,7 +2267,7 @@
}
if (pipChanging) {
- mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(true);
+ mDisplayContent.getPinnedTaskController().setPipWindowingModeChanging(true);
// If the top activity is using fixed rotation, it should be changing from PiP to
// fullscreen with display orientation change. Do not notify fullscreen task organizer
// because the restoration of task surface and the transformation of activity surface
@@ -2297,7 +2297,7 @@
}
} finally {
if (pipChanging) {
- mDisplayContent.getPinnedStackController().setPipWindowingModeChanging(false);
+ mDisplayContent.getPinnedTaskController().setPipWindowingModeChanging(false);
}
}
@@ -2361,9 +2361,7 @@
final int newRotation = getWindowConfiguration().getRotation();
final boolean rotationChanged = prevRotation != newRotation;
if (rotationChanged) {
- mDisplayContent.rotateBounds(
- newParentConfig.windowConfiguration.getBounds(), prevRotation, newRotation,
- newBounds);
+ mDisplayContent.rotateBounds(prevRotation, newRotation, newBounds);
setBounds(newBounds);
}
}
@@ -7792,18 +7790,18 @@
return;
}
- final PinnedStackController pinnedStackController =
- getDisplayContent().getPinnedStackController();
+ final PinnedTaskController pinnedTaskController =
+ getDisplayContent().getPinnedTaskController();
- if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) {
+ if (Float.compare(aspectRatio, pinnedTaskController.getAspectRatio()) == 0) {
return;
}
// Notify the pinned stack controller about aspect ratio change.
// This would result a callback delivered from SystemUI to WM to start animation,
// if the bounds are ought to be altered due to aspect ratio change.
- pinnedStackController.setAspectRatio(
- pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
+ pinnedTaskController.setAspectRatio(
+ pinnedTaskController.isValidPictureInPictureAspectRatio(aspectRatio)
? aspectRatio : -1f);
}
@@ -7819,7 +7817,7 @@
return;
}
- getDisplayContent().getPinnedStackController().setActions(actions);
+ getDisplayContent().getPinnedTaskController().setActions(actions);
}
/** Returns true if a removal action is still being deferred. */
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 9b72570..04ec4bd 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -130,8 +130,8 @@
l.onActivityForcedResizable((String) m.obj, m.arg1, m.arg2);
};
- private final TaskStackConsumer mNotifyActivityDismissingDockedStack = (l, m) -> {
- l.onActivityDismissingDockedStack();
+ private final TaskStackConsumer mNotifyActivityDismissingDockedTask = (l, m) -> {
+ l.onActivityDismissingDockedTask();
};
private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayFailed = (l, m) -> {
@@ -235,7 +235,7 @@
forAllRemoteListeners(mNotifyActivityForcedResizable, msg);
break;
case NOTIFY_ACTIVITY_DISMISSING_DOCKED_ROOT_TASK_MSG:
- forAllRemoteListeners(mNotifyActivityDismissingDockedStack, msg);
+ forAllRemoteListeners(mNotifyActivityDismissingDockedTask, msg);
break;
case NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG:
forAllRemoteListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
@@ -391,7 +391,7 @@
void notifyActivityDismissingDockedRootTask() {
mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_ROOT_TASK_MSG);
final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_ROOT_TASK_MSG);
- forAllLocalListeners(mNotifyActivityDismissingDockedStack, msg);
+ forAllLocalListeners(mNotifyActivityDismissingDockedTask, msg);
msg.sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index c0bce6b..1531e56 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -596,9 +596,7 @@
try {
synchronized (mGlobalLock) {
final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
- if (wc == null) {
- throw new IllegalArgumentException("Can't resolve window from token");
- }
+ if (wc == null) return false;
final Task task = wc.asTask();
if (task == null) return false;
if (!task.mCreatedByOrganizer) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 89d3040..cca85b2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -230,7 +230,7 @@
import android.view.IDisplayWindowRotationController;
import android.view.IInputFilter;
import android.view.IOnKeyguardExitResult;
-import android.view.IPinnedStackListener;
+import android.view.IPinnedTaskListener;
import android.view.IRecentsAnimationRunner;
import android.view.IRotationWatcher;
import android.view.IScrollCaptureCallbacks;
@@ -2393,15 +2393,9 @@
}
}
- // We may be deferring layout passes at the moment, but since the client is interested
- // in the new out values right now we need to force a layout.
- mWindowPlacerLocked.performSurfacePlacement(true /* force */);
-
+ // Create surfaceControl before surface placement otherwise layout will be skipped
+ // (because WS.isGoneForLayout() is true when there is no surface.
if (shouldRelayout) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
-
- result = win.relayoutVisibleWindow(result);
-
try {
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
} catch (Exception e) {
@@ -2413,6 +2407,17 @@
Binder.restoreCallingIdentity(origId);
return 0;
}
+ }
+
+ // We may be deferring layout passes at the moment, but since the client is interested
+ // in the new out values right now we need to force a layout.
+ mWindowPlacerLocked.performSurfacePlacement(true /* force */);
+
+ if (shouldRelayout) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
+
+ result = win.relayoutVisibleWindow(result);
+
if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
focusMayChange = true;
}
@@ -2981,7 +2986,7 @@
}
boolean isValidPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio) {
- return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio(
+ return displayContent.getPinnedTaskController().isValidPictureInPictureAspectRatio(
aspectRatio);
}
@@ -6880,7 +6885,7 @@
}
@Override
- public void setDockedStackDividerTouchRegion(Rect touchRegion) {
+ public void setDockedTaskDividerTouchRegion(Rect touchRegion) {
synchronized (mGlobalLock) {
final DisplayContent dc = getDefaultDisplayContentLocked();
dc.getDockedDividerController().setTouchRegion(touchRegion);
@@ -6905,10 +6910,9 @@
return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, displayMetrics);
}
- @Override
- public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) {
+ public void registerPinnedTaskListener(int displayId, IPinnedTaskListener listener) {
if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS,
- "registerPinnedStackListener()")) {
+ "registerPinnedTaskListener()")) {
return;
}
if (!mAtmService.mSupportsPictureInPicture) {
@@ -6916,7 +6920,7 @@
}
synchronized (mGlobalLock) {
final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
- displayContent.getPinnedStackController().registerPinnedStackListener(listener);
+ displayContent.getPinnedTaskController().registerPinnedTaskListener(listener);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 63a0832..9973664 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.Manifest.permission.READ_FRAME_BUFFER;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
@@ -426,8 +425,9 @@
}
if (windowingMode > -1) {
- if (mService.isInLockTaskMode() && windowingMode != WINDOWING_MODE_FULLSCREEN) {
- throw new UnsupportedOperationException("Not supported to set non-fullscreen"
+ if (mService.isInLockTaskMode()
+ && WindowConfiguration.inMultiWindowMode(windowingMode)) {
+ throw new UnsupportedOperationException("Not supported to set multi-window"
+ " windowing mode during locked task mode.");
}
container.setWindowingMode(windowingMode);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 60e95e5..9ae5beb 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1224,7 +1224,7 @@
// But in docked we want to behave like fullscreen and behave as if the task
// were given smaller bounds for the purposes of layout. Skip adjustments for
// the root pinned task, they are handled separately in the
- // PinnedStackController.
+ // PinnedTaskController.
windowFrames.mContainingFrame.bottom = windowFrames.mParentFrame.bottom;
}
}
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 4551d49..8735847 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -86,7 +86,7 @@
int pidfd = syscall(__NR_pidfd_open, pid, 0);
err = -errno;
- if (err < 0) {
+ if (pidfd < 0) {
// Skip compaction if failed to open pidfd with any error
return err;
}
@@ -232,21 +232,6 @@
compactProcessOrFallback(pid, compactionFlags);
}
-static void com_android_server_am_CachedAppOptimizer_enableFreezerInternal(
- JNIEnv *env, jobject clazz, jboolean enable) {
- bool success = true;
-
- if (enable) {
- success = SetTaskProfiles(0, {"FreezerEnabled"}, true);
- } else {
- success = SetTaskProfiles(0, {"FreezerDisabled"}, true);
- }
-
- if (!success) {
- jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
- }
-}
-
static void com_android_server_am_CachedAppOptimizer_freezeBinder(
JNIEnv *env, jobject clazz, jint pid, jboolean freeze) {
@@ -287,8 +272,6 @@
/* name, signature, funcPtr */
{"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
{"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess},
- {"enableFreezerInternal", "(Z)V",
- (void*)com_android_server_am_CachedAppOptimizer_enableFreezerInternal},
{"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder},
{"getBinderFreezeInfo", "(I)I",
(void*)com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo},
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 21d57d8..10705af 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -331,7 +331,7 @@
uint32_t policyFlags) override;
bool dispatchUnhandledKey(const sp<IBinder>& token, const KeyEvent* keyEvent,
uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) override;
- void pokeUserActivity(nsecs_t eventTime, int32_t eventType) override;
+ void pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) override;
bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid, int32_t injectorUid) override;
void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
void setPointerCapture(bool enabled) override;
@@ -1325,9 +1325,9 @@
return result;
}
-void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
+void NativeInputManager::pokeUserActivity(nsecs_t eventTime, int32_t eventType, int32_t displayId) {
ATRACE_CALL();
- android_server_PowerManagerService_userActivity(eventTime, eventType);
+ android_server_PowerManagerService_userActivity(eventTime, eventType, displayId);
}
bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 63a6eed..9b7e27d 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -103,7 +103,8 @@
return result == power::HalResult::SUCCESSFUL;
}
-void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
+void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,
+ int32_t displayId) {
if (gPowerManagerServiceObj) {
// Throttle calls into user activity by event type.
// We're a little conservative about argument checking here in case the caller
@@ -127,7 +128,7 @@
env->CallVoidMethod(gPowerManagerServiceObj,
gPowerManagerServiceClassInfo.userActivityFromNative,
- nanoseconds_to_milliseconds(eventTime), eventType, 0);
+ nanoseconds_to_milliseconds(eventTime), eventType, displayId, 0);
checkAndClearExceptionFromCallback(env, "userActivityFromNative");
}
}
@@ -285,7 +286,7 @@
FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
- "userActivityFromNative", "(JII)V");
+ "userActivityFromNative", "(JIII)V");
// Initialize
for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.h b/services/core/jni/com_android_server_power_PowerManagerService.h
index a17fd65..a2f335c 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.h
+++ b/services/core/jni/com_android_server_power_PowerManagerService.h
@@ -24,7 +24,8 @@
namespace android {
-extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);
+extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType,
+ int32_t displayId);
} // namespace android
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index b52347f..ef7afc8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -129,6 +129,15 @@
FullyManagedDeviceProvisioningParams provisioningParams, String callerPackage) {
}
+ @Override
+ public void setDeviceOwnerType(@NonNull ComponentName admin, int deviceOwnerType) {
+ }
+
+ @Override
+ public int getDeviceOwnerType(@NonNull ComponentName admin) {
+ return 0;
+ }
+
public void resetDefaultCrossProfileIntentFilters(@UserIdInt int userId) {}
public boolean canAdminGrantSensorsPermissionsForUser(int userId) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7260732..524892b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -156,6 +156,7 @@
import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManager;
+import android.app.admin.DevicePolicyManager.DeviceOwnerType;
import android.app.admin.DevicePolicyManager.DevicePolicyOperation;
import android.app.admin.DevicePolicyManager.OperationSafetyReason;
import android.app.admin.DevicePolicyManager.PasswordComplexity;
@@ -333,6 +334,7 @@
import org.xmlpull.v1.XmlPullParserException;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -340,6 +342,9 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
@@ -3399,8 +3404,10 @@
return;
}
Objects.requireNonNull(adminReceiver, "ComponentName is null");
- Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()),
- "Non-shell user attempted to call forceRemoveActiveAdmin");
+ Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS),
+ "Caller must be shell or hold MANAGE_PROFILE_AND_DEVICE_OWNERS to call "
+ + "forceRemoveActiveAdmin");
mInjector.binderWithCleanCallingIdentity(() -> {
synchronized (getLockObject()) {
if (!isAdminTestOnlyLocked(adminReceiver, userHandle)) {
@@ -5622,7 +5629,7 @@
// Get attestation flags, if any.
final int[] attestationUtilsFlags = translateIdAttestationFlags(idAttestationFlags);
final boolean deviceIdAttestationRequired = attestationUtilsFlags != null;
- final KeyGenParameterSpec keySpec = parcelableKeySpec.getSpec();
+ KeyGenParameterSpec keySpec = parcelableKeySpec.getSpec();
final String alias = keySpec.getKeystoreAlias();
Preconditions.checkStringNotEmpty(alias, "Empty alias provided");
@@ -5643,6 +5650,9 @@
|| (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
}
+ if (TextUtils.isEmpty(alias)) {
+ throw new IllegalArgumentException("Empty alias provided.");
+ }
// 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) {
@@ -5651,19 +5661,26 @@
return false;
}
+ if (deviceIdAttestationRequired) {
+ if (keySpec.getAttestationChallenge() == null) {
+ throw new IllegalArgumentException(
+ "Requested Device ID attestation but challenge is empty.");
+ }
+ KeyGenParameterSpec.Builder specBuilder = new KeyGenParameterSpec.Builder(keySpec);
+ specBuilder.setAttestationIds(attestationUtilsFlags);
+ specBuilder.setDevicePropertiesAttestationIncluded(true);
+ keySpec = specBuilder.build();
+ }
+
+ final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
final long id = mInjector.binderClearCallingIdentity();
try {
try (KeyChainConnection keyChainConnection =
- KeyChain.bindAsUser(mContext, caller.getUserHandle())) {
+ KeyChain.bindAsUser(mContext, userHandle)) {
IKeyChainService keyChain = keyChainConnection.getService();
- // Copy the provided keySpec, excluding the attestation challenge, which will be
- // used later for requesting key attestation record.
- final KeyGenParameterSpec noAttestationSpec = new KeyGenParameterSpec.Builder(
- keySpec).setAttestationChallenge(null).build();
-
final int generationResult = keyChain.generateKeyPair(algorithm,
- new ParcelableKeyGenParameterSpec(noAttestationSpec));
+ new ParcelableKeyGenParameterSpec(keySpec));
if (generationResult != KeyChain.KEY_GEN_SUCCESS) {
Log.e(LOG_TAG, String.format(
"KeyChain failed to generate a keypair, error %d.", generationResult));
@@ -5672,6 +5689,9 @@
throw new ServiceSpecificException(
DevicePolicyManager.KEY_GEN_STRONGBOX_UNAVAILABLE,
String.format("KeyChain error: %d", generationResult));
+ case KeyChain.KEY_ATTESTATION_CANNOT_ATTEST_IDS:
+ throw new UnsupportedOperationException(
+ "Device does not support Device ID attestation.");
default:
logGenerateKeyPairFailure(caller, isCredentialManagementApp);
return false;
@@ -5685,23 +5705,27 @@
// that UID.
keyChain.setGrant(caller.getUid(), alias, true);
- final byte[] attestationChallenge = keySpec.getAttestationChallenge();
- if (attestationChallenge != null) {
- final int attestationResult = keyChain.attestKey(
- alias, attestationChallenge, attestationUtilsFlags, attestationChain);
- if (attestationResult != KeyChain.KEY_ATTESTATION_SUCCESS) {
- Log.e(LOG_TAG, String.format(
- "Attestation for %s failed (rc=%d), deleting key.",
- alias, attestationResult));
- keyChain.removeKeyPair(alias);
- if (attestationResult == KeyChain.KEY_ATTESTATION_CANNOT_ATTEST_IDS) {
- throw new UnsupportedOperationException(
- "Device does not support Device ID attestation.");
+ try {
+ final List<byte[]> encodedCerts = new ArrayList();
+ final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ final byte[] certChainBytes = keyChain.getCaCertificates(alias);
+ encodedCerts.add(keyChain.getCertificate(alias));
+ if (certChainBytes != null) {
+ final Collection<X509Certificate> certs =
+ (Collection<X509Certificate>) certFactory.generateCertificates(
+ new ByteArrayInputStream(certChainBytes));
+ for (X509Certificate cert : certs) {
+ encodedCerts.add(cert.getEncoded());
}
- logGenerateKeyPairFailure(caller, isCredentialManagementApp);
- return false;
}
+
+ attestationChain.shallowCopyFrom(new KeymasterCertificateChain(encodedCerts));
+ } catch (CertificateException e) {
+ logGenerateKeyPairFailure(caller, isCredentialManagementApp);
+ Log.e(LOG_TAG, "While retrieving certificate chain.", e);
+ return false;
}
+
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.GENERATE_KEY_PAIR)
.setAdmin(caller.getPackageName())
@@ -7560,8 +7584,7 @@
}
private void sendProfileOwnerCommand(String action, Bundle extras, @UserIdInt int userId) {
- sendActiveAdminCommand(action, extras, userId,
- mOwners.getProfileOwnerComponent(userId));
+ sendActiveAdminCommand(action, extras, userId, mOwners.getProfileOwnerComponent(userId));
}
private void sendActiveAdminCommand(String action, Bundle extras,
@@ -8089,7 +8112,8 @@
return null;
}
if (!callingUserOnly) {
- Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+ Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
}
synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
@@ -12351,8 +12375,10 @@
extras.putInt(DeviceAdminReceiver.EXTRA_OPERATION_SAFETY_REASON, reason);
extras.putBoolean(DeviceAdminReceiver.EXTRA_OPERATION_SAFETY_STATE, isSafe);
- sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_OPERATION_SAFETY_STATE_CHANGED,
- extras);
+ if (mOwners.hasDeviceOwner()) {
+ sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_OPERATION_SAFETY_STATE_CHANGED,
+ extras);
+ }
for (int profileOwnerId : mOwners.getProfileOwnerKeys()) {
sendProfileOwnerCommand(DeviceAdminReceiver.ACTION_OPERATION_SAFETY_STATE_CHANGED,
extras, profileOwnerId);
@@ -12543,8 +12569,10 @@
@Override
public void clearSystemUpdatePolicyFreezePeriodRecord() {
- Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()),
- "Non-shell user attempted to call clearSystemUpdatePolicyFreezePeriodRecord");
+ Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.CLEAR_FREEZE_PERIOD),
+ "Caller must be shell, or hold CLEAR_FREEZE_PERIOD permission to call "
+ + "clearSystemUpdatePolicyFreezePeriodRecord");
synchronized (getLockObject()) {
// Print out current record to help diagnosed CTS failures
Slog.i(LOG_TAG, "Clear freeze period record: "
@@ -13487,7 +13515,8 @@
final CallerIdentity caller = getCallerIdentity();
// Only adb or system apps with the right permission can mark a profile owner on
// organization-owned device.
- if (!(isAdb(caller) || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED))) {
+ if (!(isAdb(caller) || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED)
+ || hasCallingPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS))) {
throw new SecurityException(
"Only the system can mark a profile owner of organization-owned device.");
}
@@ -13806,8 +13835,10 @@
@Override
public long forceSecurityLogs() {
- Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()),
- "Non-shell user attempted to call forceSecurityLogs");
+ Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.FORCE_DEVICE_POLICY_MANAGER_LOGS),
+ "Caller must be shell or hold FORCE_DEVICE_POLICY_MANAGER_LOGS to call "
+ + "forceSecurityLogs");
if (!mInjector.securityLogGetLoggingEnabledProperty()) {
throw new IllegalStateException("logging is not available");
}
@@ -14327,8 +14358,10 @@
@Override
public long forceNetworkLogs() {
- Preconditions.checkCallAuthorization(isAdb(getCallerIdentity()),
- "Non-shell user attempted to call forceNetworkLogs");
+ Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
+ || hasCallingOrSelfPermission(permission.FORCE_DEVICE_POLICY_MANAGER_LOGS),
+ "Caller must be shell or hold FORCE_DEVICE_POLICY_MANAGER_LOGS to call "
+ + "forceNetworkLogs");
synchronized (getLockObject()) {
if (!isNetworkLoggingEnabledInternalLocked()) {
throw new IllegalStateException("logging is not available");
@@ -16731,6 +16764,37 @@
}
@Override
+ public void setDeviceOwnerType(@NonNull ComponentName admin,
+ @DeviceOwnerType int deviceOwnerType) {
+ Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
+ permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
+ verifyDeviceOwnerTypePreconditions(admin);
+
+ final String packageName = admin.getPackageName();
+ Preconditions.checkState(!mOwners.isDeviceOwnerTypeSetForDeviceOwner(packageName),
+ "The device owner type has already been set for " + packageName);
+
+ synchronized (getLockObject()) {
+ mOwners.setDeviceOwnerType(packageName, deviceOwnerType);
+ }
+ }
+
+ @Override
+ @DeviceOwnerType
+ public int getDeviceOwnerType(@NonNull ComponentName admin) {
+ verifyDeviceOwnerTypePreconditions(admin);
+ synchronized (getLockObject()) {
+ return mOwners.getDeviceOwnerType(admin.getPackageName());
+ }
+ }
+
+ private void verifyDeviceOwnerTypePreconditions(@NonNull ComponentName admin) {
+ Preconditions.checkState(mOwners.hasDeviceOwner(), "there is no device owner");
+ Preconditions.checkState(mOwners.getDeviceOwnerComponent().equals(admin),
+ "admin is not the device owner");
+ }
+
+ @Override
public void setUsbDataSignalingEnabled(String packageName, boolean enabled) {
Objects.requireNonNull(packageName, "Admin package name must be provided");
final CallerIdentity caller = getCallerIdentity(packageName);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java b/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
index 776b444..257fc64 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OneTimeSafetyChecker.java
@@ -23,6 +23,8 @@
import android.app.admin.DevicePolicyManager.OperationSafetyReason;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DevicePolicySafetyChecker;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Slog;
import com.android.internal.os.IResultReceiver;
@@ -42,10 +44,15 @@
private static final String TAG = OneTimeSafetyChecker.class.getSimpleName();
+ private static final long SELF_DESTRUCT_TIMEOUT_MS = 10_000;
+
private final DevicePolicyManagerService mService;
private final DevicePolicySafetyChecker mRealSafetyChecker;
private final @DevicePolicyOperation int mOperation;
private final @OperationSafetyReason int mReason;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+ private boolean mDone;
OneTimeSafetyChecker(DevicePolicyManagerService service,
@DevicePolicyOperation int operation, @OperationSafetyReason int reason) {
@@ -53,7 +60,11 @@
mOperation = operation;
mReason = reason;
mRealSafetyChecker = service.getDevicePolicySafetyChecker();
- Slog.i(TAG, "Saving real DevicePolicySafetyChecker as " + mRealSafetyChecker);
+ Slog.i(TAG, "OneTimeSafetyChecker constructor: operation= " + operationToString(operation)
+ + ", reason=" + operationSafetyReasonToString(reason)
+ + ", realChecker=" + mRealSafetyChecker
+ + ", maxDuration=" + SELF_DESTRUCT_TIMEOUT_MS + "ms");
+ mHandler.postDelayed(() -> selfDestruct(), SELF_DESTRUCT_TIMEOUT_MS);
}
@Override
@@ -99,8 +110,21 @@
}
private void disableSelf() {
+ if (mDone) {
+ Slog.w(TAG, "disableSelf(): already disabled");
+ return;
+ }
Slog.i(TAG, "restoring DevicePolicySafetyChecker to " + mRealSafetyChecker);
mService.setDevicePolicySafetyCheckerUnchecked(mRealSafetyChecker);
+ mDone = true;
+ }
+
+ private void selfDestruct() {
+ if (mDone) return;
+
+ // Usually happens when a CTS failed before calling the DPM method that would clear it
+ Slog.e(TAG, "Self destructing " + this + ", as it was not automatically disabled");
+ disableSelf();
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index 1e70d59..7fdd6ee 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -16,10 +16,13 @@
package com.android.server.devicepolicy;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManagerInternal;
+import android.app.admin.DevicePolicyManager.DeviceOwnerType;
import android.app.admin.SystemUpdateInfo;
import android.app.admin.SystemUpdatePolicy;
import android.content.ComponentName;
@@ -93,6 +96,7 @@
private static final String TAG_PROFILE_OWNER = "profile-owner";
// Holds "context" for device-owner, this must not be show up before device-owner.
private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context";
+ private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type";
private static final String ATTR_NAME = "name";
private static final String ATTR_PACKAGE = "package";
@@ -109,6 +113,7 @@
// New attribute for profile owner of organization-owned device.
private static final String ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE =
"isPoOrganizationOwnedDevice";
+ private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value";
private final UserManager mUserManager;
private final UserManagerInternal mUserManagerInternal;
@@ -121,6 +126,9 @@
// Internal state for the device owner package.
private OwnerInfo mDeviceOwner;
+ // Device owner type for a managed device.
+ private final ArrayMap<String, Integer> mDeviceOwnerTypes = new ArrayMap<>();
+
private int mDeviceOwnerUserId = UserHandle.USER_NULL;
// Internal state for the profile owner packages.
@@ -334,6 +342,7 @@
void clearDeviceOwner() {
synchronized (mLock) {
+ mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
mDeviceOwner = null;
mDeviceOwnerUserId = UserHandle.USER_NULL;
@@ -384,12 +393,16 @@
void transferDeviceOwnership(ComponentName target) {
synchronized (mLock) {
+ Integer previousDeviceOwnerType = mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
// We don't set a name because it's not used anyway.
// See DevicePolicyManagerService#getDeviceOwnerName
mDeviceOwner = new OwnerInfo(null, target,
mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri,
mDeviceOwner.remoteBugreportHash, /* isOrganizationOwnedDevice =*/
mDeviceOwner.isOrganizationOwnedDevice);
+ if (previousDeviceOwnerType != null) {
+ mDeviceOwnerTypes.put(mDeviceOwner.packageName, previousDeviceOwnerType);
+ }
pushToPackageManagerLocked();
pushToActivityTaskManagerLocked();
pushToActivityManagerLocked();
@@ -596,6 +609,37 @@
}
}
+ void setDeviceOwnerType(String packageName, @DeviceOwnerType int deviceOwnerType) {
+ synchronized (mLock) {
+ if (!hasDeviceOwner()) {
+ Slog.e(TAG, "Attempting to set a device owner type when there is no device owner");
+ return;
+ } else if (isDeviceOwnerTypeSetForDeviceOwner(packageName)) {
+ Slog.e(TAG, "Device owner type for " + packageName + " has already been set");
+ return;
+ }
+
+ mDeviceOwnerTypes.put(packageName, deviceOwnerType);
+ writeDeviceOwner();
+ }
+ }
+
+ @DeviceOwnerType
+ int getDeviceOwnerType(String packageName) {
+ synchronized (mLock) {
+ if (isDeviceOwnerTypeSetForDeviceOwner(packageName)) {
+ return mDeviceOwnerTypes.get(packageName);
+ }
+ return DEVICE_OWNER_TYPE_DEFAULT;
+ }
+ }
+
+ boolean isDeviceOwnerTypeSetForDeviceOwner(String packageName) {
+ synchronized (mLock) {
+ return !mDeviceOwnerTypes.isEmpty() && mDeviceOwnerTypes.containsKey(packageName);
+ }
+ }
+
private boolean readLegacyOwnerFileLocked(File file) {
if (!file.exists()) {
// Already migrated or the device has no owners.
@@ -880,6 +924,16 @@
out.startTag(null, TAG_DEVICE_OWNER_CONTEXT);
out.attributeInt(null, ATTR_USERID, mDeviceOwnerUserId);
out.endTag(null, TAG_DEVICE_OWNER_CONTEXT);
+
+ }
+
+ if (!mDeviceOwnerTypes.isEmpty()) {
+ for (ArrayMap.Entry<String, Integer> entry : mDeviceOwnerTypes.entrySet()) {
+ out.startTag(null, TAG_DEVICE_OWNER_TYPE);
+ out.attribute(null, ATTR_PACKAGE, entry.getKey());
+ out.attributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE, entry.getValue());
+ out.endTag(null, TAG_DEVICE_OWNER_TYPE);
+ }
}
if (mSystemUpdatePolicy != null) {
@@ -942,6 +996,12 @@
}
}
break;
+ case TAG_DEVICE_OWNER_TYPE:
+ String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+ int deviceOwnerType = parser.getAttributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE,
+ DEVICE_OWNER_TYPE_DEFAULT);
+ mDeviceOwnerTypes.put(packageName, deviceOwnerType);
+ break;
default:
Slog.e(TAG, "Unexpected tag: " + tag);
return false;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2bb5798..a3d3353 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -104,7 +104,6 @@
import com.android.internal.widget.ILockSettings;
import com.android.server.am.ActivityManagerService;
import com.android.server.appbinding.AppBindingService;
-import com.android.server.apphibernation.AppHibernationService;
import com.android.server.attention.AttentionManagerService;
import com.android.server.audio.AudioService;
import com.android.server.biometrics.AuthService;
@@ -163,6 +162,7 @@
import com.android.server.pm.UserManagerService;
import com.android.server.pm.dex.SystemServerDexLoadReporter;
import com.android.server.pm.verify.domain.DomainVerificationService;
+import com.android.server.policy.AppOpsPolicy;
import com.android.server.policy.PermissionPolicyService;
import com.android.server.policy.PhoneWindowManager;
import com.android.server.policy.role.RoleServicePlatformHelperImpl;
@@ -1718,14 +1718,9 @@
startTextToSpeechManagerService(context, t);
// System Speech Recognition Service
- if (deviceHasConfigString(context,
- R.string.config_defaultOnDeviceSpeechRecognitionService)) {
- t.traceBegin("StartSpeechRecognitionManagerService");
- mSystemServiceManager.startService(SPEECH_RECOGNITION_MANAGER_SERVICE_CLASS);
- t.traceEnd();
- } else {
- Slog.d(TAG, "System speech recognition is not defined by OEM");
- }
+ t.traceBegin("StartSpeechRecognitionManagerService");
+ mSystemServiceManager.startService(SPEECH_RECOGNITION_MANAGER_SERVICE_CLASS);
+ t.traceEnd();
// App prediction manager service
if (deviceHasConfigString(context, R.string.config_defaultAppPredictionService)) {
@@ -2150,11 +2145,9 @@
mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS);
t.traceEnd();
- if (AppHibernationService.isAppHibernationEnabled()) {
- t.traceBegin("StartAppHibernationService");
- mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS);
- t.traceEnd();
- }
+ t.traceBegin("StartAppHibernationService");
+ mSystemServiceManager.startService(APP_HIBERNATION_SERVICE_CLASS);
+ t.traceEnd();
if (GestureLauncherService.isGestureLauncherEnabled(context.getResources())) {
t.traceBegin("StartGestureLauncher");
@@ -2664,6 +2657,14 @@
}
t.traceEnd();
+ t.traceBegin("RegisterAppOpsPolicy");
+ try {
+ mActivityManagerService.setAppOpsPolicy(new AppOpsPolicy());
+ } catch (Throwable e) {
+ reportWtf("registering app ops policy", e);
+ }
+ t.traceEnd();
+
// No dependency on Webview preparation in system server. But this should
// be completed before allowing 3rd party
final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
diff --git a/services/musicrecognition/Android.bp b/services/musicrecognition/Android.bp
index fea9efa..8298dec 100644
--- a/services/musicrecognition/Android.bp
+++ b/services/musicrecognition/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "services.musicsearch-sources",
srcs: ["java/**/*.java"],
@@ -10,4 +19,4 @@
defaults: ["platform_service_defaults"],
srcs: [":services.musicsearch-sources"],
libs: ["services.core", "app-compat-annotations"],
-}
\ No newline at end of file
+}
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
index cbebe69..2219d47 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
@@ -38,7 +38,6 @@
import android.annotation.UserIdInt;
import android.app.Application;
-import android.app.backup.BackupManager.OperationType;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
@@ -874,8 +873,7 @@
SecurityException.class,
() ->
backupManagerService.requestBackup(
- mUserTwoId, packages, observer, monitor, 0,
- OperationType.BACKUP));
+ mUserTwoId, packages, observer, monitor, 0));
}
/**
@@ -893,11 +891,9 @@
IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true);
- backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0,
- OperationType.BACKUP);
+ backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0);
- verify(mUserTwoService).requestBackup(packages, observer, monitor, /* flags */ 0,
- OperationType.BACKUP);
+ verify(mUserTwoService).requestBackup(packages, observer, monitor, /* flags */ 0);
}
/** Test that the backup service routes methods correctly to the user that requests it. */
@@ -910,11 +906,9 @@
IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
- backupManagerService.requestBackup(mUserOneId, packages, observer, monitor, /* flags */ 0,
- OperationType.BACKUP);
+ backupManagerService.requestBackup(mUserOneId, packages, observer, monitor, /* flags */ 0);
- verify(mUserOneService).requestBackup(packages, observer, monitor, /* flags */ 0,
- OperationType.BACKUP);
+ verify(mUserOneService).requestBackup(packages, observer, monitor, /* flags */ 0);
}
/** Test that the backup service routes methods correctly to the user that requests it. */
@@ -927,11 +921,9 @@
IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class);
setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
- backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0,
- OperationType.BACKUP);
+ backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0);
- verify(mUserOneService, never()).requestBackup(packages, observer, monitor, /* flags */ 0,
- OperationType.BACKUP);
+ verify(mUserOneService, never()).requestBackup(packages, observer, monitor, /* flags */ 0);
}
/**
@@ -1092,11 +1084,9 @@
registerUser(backupManagerService, mUserOneId, mUserOneService);
setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
- backupManagerService.beginRestoreSession(mUserOneId, TEST_PACKAGE, TEST_TRANSPORT,
- OperationType.BACKUP);
+ backupManagerService.beginRestoreSession(mUserOneId, TEST_PACKAGE, TEST_TRANSPORT);
- verify(mUserOneService).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT,
- OperationType.BACKUP);
+ verify(mUserOneService).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT);
}
/** Test that the backup service does not route methods for non-registered users. */
@@ -1106,11 +1096,9 @@
registerUser(backupManagerService, mUserOneId, mUserOneService);
setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
- backupManagerService.beginRestoreSession(mUserTwoId, TEST_PACKAGE, TEST_TRANSPORT,
- OperationType.BACKUP);
+ backupManagerService.beginRestoreSession(mUserTwoId, TEST_PACKAGE, TEST_TRANSPORT);
- verify(mUserOneService, never()).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT,
- OperationType.BACKUP);
+ verify(mUserOneService, never()).beginRestoreSession(TEST_PACKAGE, TEST_TRANSPORT);
}
/** Test that the backup service routes methods correctly to the user that requests it. */
diff --git a/services/searchui/Android.bp b/services/searchui/Android.bp
index cc63294..3081a51 100644
--- a/services/searchui/Android.bp
+++ b/services/searchui/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "services.searchui-sources",
srcs: ["java/**/*.java"],
diff --git a/services/smartspace/Android.bp b/services/smartspace/Android.bp
index fcf780d..640a88d 100644
--- a/services/smartspace/Android.bp
+++ b/services/smartspace/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "services.smartspace-sources",
srcs: ["java/**/*.java"],
diff --git a/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp
index b7a0624..e70a734 100644
--- a/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/libs/IntentVerifyUtils/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_library {
name: "PackageManagerServiceHostTestsIntentVerifyUtils",
srcs: ["src/**/*.kt"],
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
index af0ac77..7e4f0e7 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test_helper_app {
name: "PackageManagerServiceDeviceSideTests",
sdk_version: "test_current",
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp
index e82f57d..4f3f2eb 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifier/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test_helper_app {
name: "PackageManagerTestIntentVerifier",
srcs: [ "src/**/*.kt" ],
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp
index 7161fdd..9f9ed24 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/IntentVerifierTarget/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test_helper_app {
name: "PackageManagerTestIntentVerifierTarget1",
manifest: "AndroidManifest1.xml",
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp
index 58f17f2..ebad5af 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test_helper_app {
name: "PackageManagerTestAppDeclaresStaticLibrary",
manifest: "AndroidManifestDeclaresStaticLibrary.xml",
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index 4aa8abc..334e53a 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "PackageManagerServiceUnitTests",
srcs: ["src/**/*.kt"],
diff --git a/services/tests/inprocesstests/Android.bp b/services/tests/inprocesstests/Android.bp
index 6dd059f..7c237ac 100644
--- a/services/tests/inprocesstests/Android.bp
+++ b/services/tests/inprocesstests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "FrameworksInProcessTests",
srcs: ["src/**/*.java"],
diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp
index 928065a..a32bf2c 100644
--- a/services/tests/mockingservicestests/jni/Android.bp
+++ b/services/tests/mockingservicestests/jni/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
cc_library_shared {
name: "libactivitymanagermockingservicestestjni",
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index a382e85..1c45203 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -46,6 +46,7 @@
import static com.android.server.am.ProcessList.HOME_APP_ADJ;
import static com.android.server.am.ProcessList.PERCEPTIBLE_APP_ADJ;
import static com.android.server.am.ProcessList.PERCEPTIBLE_LOW_APP_ADJ;
+import static com.android.server.am.ProcessList.PERCEPTIBLE_MEDIUM_APP_ADJ;
import static com.android.server.am.ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ;
import static com.android.server.am.ProcessList.PERSISTENT_PROC_ADJ;
import static com.android.server.am.ProcessList.PERSISTENT_SERVICE_ADJ;
@@ -877,6 +878,39 @@
@SuppressWarnings("GuardedBy")
@Test
+ public void testUpdateOomAdj_DoOne_Service_MediumPerceptible() {
+ {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ bindService(app, client, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+ client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ, app.mState.getSetAdj());
+ }
+
+ {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ WindowProcessController wpc = client.getWindowProcessController();
+ doReturn(true).when(wpc).isHeavyWeightProcess();
+ bindService(app, client, null, Context.BIND_ALMOST_PERCEPTIBLE, mock(IBinder.class));
+ client.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+ sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
+ doReturn(false).when(wpc).isHeavyWeightProcess();
+
+ assertEquals(PERCEPTIBLE_MEDIUM_APP_ADJ, app.mState.getSetAdj());
+ }
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
public void testUpdateOomAdj_DoOne_Service_Other() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 728b97c..18184b0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -27,11 +27,14 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
+import android.content.res.TypedArray;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -44,6 +47,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.internal.R;
import com.android.server.LocalServices;
import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
import com.android.server.lights.LightsManager;
@@ -98,6 +102,9 @@
@Mock
private LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy;
+ private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f };
+ private static final int[] BACKLIGHT_RANGE = { 1, 255 };
+ private static final float[] BACKLIGHT_RANGE_ZERO_TO_ONE = { 0.0f, 1.0f };
@Before
public void setUp() throws Exception {
@@ -114,6 +121,18 @@
mListener, mInjector);
spyOn(mAdapter);
doReturn(mMockedContext).when(mAdapter).getOverlayContext();
+
+ TypedArray mockNitsRange = createFloatTypedArray(DISPLAY_RANGE_NITS);
+ when(mMockedResources.obtainTypedArray(R.array.config_screenBrightnessNits))
+ .thenReturn(mockNitsRange);
+ when(mMockedResources.getIntArray(R.array.config_screenBrightnessBacklight))
+ .thenReturn(BACKLIGHT_RANGE);
+ when(mMockedResources.getFloat(com.android.internal.R.dimen
+ .config_screenBrightnessSettingMinimumFloat))
+ .thenReturn(BACKLIGHT_RANGE_ZERO_TO_ONE[0]);
+ when(mMockedResources.getFloat(com.android.internal.R.dimen
+ .config_screenBrightnessSettingMaximumFloat))
+ .thenReturn(BACKLIGHT_RANGE_ZERO_TO_ONE[1]);
}
@After
@@ -629,13 +648,13 @@
// Test as default display
BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
mSurfaceControlProxy);
- ba.setBrightness(0.514f);
+ ba.setBacklight(0.514f);
verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.514f);
// Test as not default display
BacklightAdapter ba2 = new BacklightAdapter(displayToken, false /*isDefault*/,
mSurfaceControlProxy);
- ba2.setBrightness(0.323f);
+ ba2.setBacklight(0.323f);
verify(mSurfaceControlProxy).setDisplayBrightness(displayToken, 0.323f);
}
@@ -648,7 +667,7 @@
BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/,
mSurfaceControlProxy);
- ba.setBrightness(0.123f);
+ ba.setBacklight(0.123f);
verify(mMockedBacklight).setBrightness(0.123f);
}
@@ -661,7 +680,7 @@
BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/,
mSurfaceControlProxy);
- ba.setBrightness(0.456f);
+ ba.setBacklight(0.456f);
// Adapter does not forward any brightness in this case.
verify(mMockedBacklight, never()).setBrightness(anyFloat());
@@ -864,4 +883,23 @@
}
}
+ private TypedArray createFloatTypedArray(float[] vals) {
+ TypedArray mockArray = mock(TypedArray.class);
+ when(mockArray.length()).thenAnswer(invocation -> {
+ return vals.length;
+ });
+ when(mockArray.getFloat(anyInt(), anyFloat())).thenAnswer(invocation -> {
+ final float def = (float) invocation.getArguments()[1];
+ if (vals == null) {
+ return def;
+ }
+ int idx = (int) invocation.getArguments()[0];
+ if (idx >= 0 && idx < vals.length) {
+ return vals[idx];
+ } else {
+ return def;
+ }
+ });
+ return mockArray;
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 88a691b..bf95f4c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -31,6 +31,7 @@
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.JobSchedulerService.sSystemClock;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -58,6 +59,7 @@
import android.app.IActivityManager;
import android.app.IUidObserver;
import android.app.job.JobInfo;
+import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
@@ -85,6 +87,7 @@
import com.android.server.job.JobStore;
import com.android.server.job.controllers.QuotaController.ExecutionStats;
import com.android.server.job.controllers.QuotaController.QcConstants;
+import com.android.server.job.controllers.QuotaController.ShrinkableDebits;
import com.android.server.job.controllers.QuotaController.TimingSession;
import com.android.server.usage.AppStandbyInternal;
@@ -125,6 +128,7 @@
private int mSourceUid;
private PowerAllowlistInternal.TempAllowlistChangeListener mTempAllowlistListener;
private IUidObserver mUidObserver;
+ private UsageStatsManagerInternal.UsageEventListener mUsageEventListener;
DeviceConfig.Properties.Builder mDeviceConfigPropertiesBuilder;
private MockitoSession mMockingSession;
@@ -218,6 +222,8 @@
ArgumentCaptor.forClass(IUidObserver.class);
ArgumentCaptor<PowerAllowlistInternal.TempAllowlistChangeListener> taChangeCaptor =
ArgumentCaptor.forClass(PowerAllowlistInternal.TempAllowlistChangeListener.class);
+ ArgumentCaptor<UsageStatsManagerInternal.UsageEventListener> ueListenerCaptor =
+ ArgumentCaptor.forClass(UsageStatsManagerInternal.UsageEventListener.class);
mQuotaController = new QuotaController(mJobSchedulerService,
mock(BackgroundJobsController.class), mock(ConnectivityController.class));
@@ -229,6 +235,8 @@
verify(mPowerAllowlistInternal)
.registerTempAllowlistChangeListener(taChangeCaptor.capture());
mTempAllowlistListener = taChangeCaptor.getValue();
+ verify(mUsageStatsManager).registerListener(ueListenerCaptor.capture());
+ mUsageEventListener = ueListenerCaptor.getValue();
try {
verify(activityManager).registerUidObserver(
uidObserverCaptor.capture(),
@@ -288,7 +296,7 @@
verify(foregroundUids, timeout(2 * SECOND_IN_MILLIS).times(1)).delete(eq(uid));
assertFalse(foregroundUids.get(uid));
}
- waitForQuietBackground();
+ waitForNonDelayedMessagesProcessed();
} catch (Exception e) {
fail("exception encountered: " + e.getMessage());
}
@@ -385,13 +393,8 @@
}
}
- private void waitForQuietBackground() throws Exception {
- for (int i = 0; i < 5; ++i) {
- if (!mQuotaController.isActiveBackgroundProcessing()) {
- break;
- }
- Thread.sleep(500);
- }
+ private void waitForNonDelayedMessagesProcessed() {
+ mQuotaController.getHandler().runWithScissors(() -> {}, 15_000);
}
@Test
@@ -1330,7 +1333,9 @@
timeUsedMs, 5), true);
JobStatus job = createExpeditedJobStatus("testGetMaxJobExecutionTimeLocked_EJ", 0);
setStandbyBucket(RARE_INDEX, job);
- mQuotaController.maybeStartTrackingJobLocked(job, null);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStartTrackingJobLocked(job, null);
+ }
setCharging();
synchronized (mQuotaController.mLock) {
@@ -5158,4 +5163,257 @@
eq(10 * SECOND_IN_MILLIS));
verify(handler, never()).sendMessageDelayed(any(), eq(remainingTimeMs));
}
+
+ @Test
+ public void testEJDebitTallying() {
+ setStandbyBucket(RARE_INDEX);
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
+ // 15 seconds for each 30 second chunk.
+ setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 30 * SECOND_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 15 * SECOND_IN_MILLIS);
+
+ // No history. Debits should be 0.
+ ShrinkableDebits debit = mQuotaController.getEJDebitsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(10 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // Regular job shouldn't affect EJ tally.
+ JobStatus regJob = createJobStatus("testEJDebitTallying", 1);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStartTrackingJobLocked(regJob, null);
+ mQuotaController.prepareForExecutionLocked(regJob);
+ }
+ advanceElapsedClock(5000);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStopTrackingJobLocked(regJob, null, false);
+ }
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(10 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // EJ job should affect EJ tally.
+ JobStatus eJob = createExpeditedJobStatus("testEJDebitTallying", 2);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStartTrackingJobLocked(eJob, null);
+ mQuotaController.prepareForExecutionLocked(eJob);
+ }
+ advanceElapsedClock(5 * MINUTE_IN_MILLIS);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStopTrackingJobLocked(eJob, null, false);
+ }
+ assertEquals(5 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+ assertEquals(5 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // Instantaneous event for a different user shouldn't affect tally.
+ advanceElapsedClock(5 * MINUTE_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, MINUTE_IN_MILLIS);
+
+ UsageEvents.Event event =
+ new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID + 10, event);
+ assertEquals(5 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+
+ // Instantaneous event for correct user should reduce tally.
+ advanceElapsedClock(5 * MINUTE_IN_MILLIS);
+
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ assertEquals(4 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+ assertEquals(6 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // Activity start shouldn't reduce tally, but duration with activity started should affect
+ // remaining EJ time.
+ advanceElapsedClock(5 * MINUTE_IN_MILLIS);
+ event = new UsageEvents.Event(UsageEvents.Event.ACTIVITY_RESUMED, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ advanceElapsedClock(30 * SECOND_IN_MILLIS);
+ assertEquals(4 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+ assertEquals(6 * MINUTE_IN_MILLIS + 15 * SECOND_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+ advanceElapsedClock(30 * SECOND_IN_MILLIS);
+ assertEquals(4 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+ assertEquals(6 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // With activity pausing/stopping/destroying, tally should be updated.
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+ event = new UsageEvents.Event(UsageEvents.Event.ACTIVITY_DESTROYED, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ assertEquals(3 * MINUTE_IN_MILLIS, debit.getTallyLocked());
+ assertEquals(7 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+ }
+
+ @Test
+ public void testEJDebitTallying_StaleSession() {
+ setStandbyBucket(RARE_INDEX);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_RARE_MS, 10 * MINUTE_IN_MILLIS);
+
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ TimingSession ts = new TimingSession(nowElapsed, nowElapsed + 10 * MINUTE_IN_MILLIS, 5);
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE, ts, true);
+
+ // Make the session stale.
+ advanceElapsedClock(12 * MINUTE_IN_MILLIS + mQcConstants.EJ_WINDOW_SIZE_MS);
+
+ // With lazy deletion, we don't update the tally until getRemainingEJExecutionTimeLocked()
+ // is called, so call that first.
+ assertEquals(10 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+ ShrinkableDebits debit = mQuotaController.getEJDebitsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+ assertEquals(0, debit.getTallyLocked());
+ }
+
+ /**
+ * Tests that rewards are properly accounted when there's no EJ running and the rewards exceed
+ * the accumulated debits.
+ */
+ @Test
+ public void testEJDebitTallying_RewardExceedDebits_NoActiveSession() {
+ setStandbyBucket(WORKING_INDEX);
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 30 * MINUTE_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, MINUTE_IN_MILLIS);
+
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ TimingSession ts = new TimingSession(nowElapsed - 5 * MINUTE_IN_MILLIS,
+ nowElapsed - 4 * MINUTE_IN_MILLIS, 2);
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE, ts, true);
+
+ ShrinkableDebits debit = mQuotaController.getEJDebitsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+ assertEquals(MINUTE_IN_MILLIS, debit.getTallyLocked());
+ assertEquals(29 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ advanceElapsedClock(30 * SECOND_IN_MILLIS);
+ UsageEvents.Event event =
+ new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(30 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(30 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // Excessive rewards don't increase maximum quota.
+ event = new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(30 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+ }
+
+ /**
+ * Tests that rewards are properly accounted when there's an active EJ running and the rewards
+ * exceed the accumulated debits.
+ */
+ @Test
+ public void testEJDebitTallying_RewardExceedDebits_ActiveSession() {
+ setStandbyBucket(WORKING_INDEX);
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ setDeviceConfigLong(QcConstants.KEY_EJ_LIMIT_WORKING_MS, 30 * MINUTE_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_INTERACTION_MS, MINUTE_IN_MILLIS);
+ // 15 seconds for each 30 second chunk.
+ setDeviceConfigLong(QcConstants.KEY_EJ_TOP_APP_TIME_CHUNK_SIZE_MS, 30 * SECOND_IN_MILLIS);
+ setDeviceConfigLong(QcConstants.KEY_EJ_REWARD_TOP_APP_MS, 15 * SECOND_IN_MILLIS);
+
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ TimingSession ts = new TimingSession(nowElapsed - 5 * MINUTE_IN_MILLIS,
+ nowElapsed - 4 * MINUTE_IN_MILLIS, 2);
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE, ts, true);
+
+ ShrinkableDebits debit = mQuotaController.getEJDebitsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
+ assertEquals(MINUTE_IN_MILLIS, debit.getTallyLocked());
+ assertEquals(29 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // With rewards coming in while an EJ is running, the remaining execution time should be
+ // adjusted accordingly (decrease due to EJ running + increase from reward).
+ JobStatus eJob =
+ createExpeditedJobStatus("testEJDebitTallying_RewardExceedDebits_ActiveSession", 1);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStartTrackingJobLocked(eJob, null);
+ mQuotaController.prepareForExecutionLocked(eJob);
+ }
+ advanceElapsedClock(30 * SECOND_IN_MILLIS);
+ assertEquals(MINUTE_IN_MILLIS, debit.getTallyLocked());
+ assertEquals(28 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ advanceElapsedClock(30 * SECOND_IN_MILLIS);
+ UsageEvents.Event event =
+ new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(29 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(28 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // Activity start shouldn't reduce tally, but duration with activity started should affect
+ // remaining EJ time.
+ event = new UsageEvents.Event(UsageEvents.Event.ACTIVITY_RESUMED, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ advanceElapsedClock(30 * SECOND_IN_MILLIS);
+ assertEquals(0, debit.getTallyLocked());
+ // Decrease by 30 seconds for running EJ, increase by 15 seconds due to ongoing activity.
+ assertEquals(27 * MINUTE_IN_MILLIS + 45 * SECOND_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+ advanceElapsedClock(30 * SECOND_IN_MILLIS);
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(27 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(27 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ event = new UsageEvents.Event(UsageEvents.Event.USER_INTERACTION, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(28 * MINUTE_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(27 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ // At this point, with activity pausing/stopping/destroying, since we're giving a reward,
+ // tally should remain 0, and time remaining shouldn't change since it was accounted for
+ // at every step.
+ event = new UsageEvents.Event(UsageEvents.Event.ACTIVITY_DESTROYED, sSystemClock.millis());
+ event.mPackage = SOURCE_PACKAGE;
+ mUsageEventListener.onUsageEvent(SOURCE_USER_ID, event);
+ waitForNonDelayedMessagesProcessed();
+ assertEquals(0, debit.getTallyLocked());
+ assertEquals(27 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS,
+ mQuotaController.getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index 66b037d..c4c9ad0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -123,9 +123,10 @@
.setPowerUsage(POWER_USAGE_HIGH)
.setAccuracy(ProviderProperties.ACCURACY_FINE)
.build();
+ private static final CallerIdentity PROVIDER_IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1,
+ "mypackage", "attribution");
private static final CallerIdentity IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1,
- "mypackage",
- "attribution");
+ "mypackage", "attribution", "listener");
private static final WorkSource WORK_SOURCE = new WorkSource(IDENTITY.getUid());
private Random mRandom;
@@ -169,7 +170,7 @@
mPassive.startManager();
mPassive.setRealProvider(new PassiveLocationProvider(mContext));
- mProvider = new TestProvider(PROPERTIES, IDENTITY);
+ mProvider = new TestProvider(PROPERTIES, PROVIDER_IDENTITY);
mProvider.setProviderAllowed(true);
mManager = new LocationProviderManager(mContext, mInjector, eventLog, NAME, mPassive);
@@ -351,7 +352,8 @@
@Test
public void testGetLastLocation_ClearOnMockRemoval() {
- MockLocationProvider mockProvider = new MockLocationProvider(PROPERTIES, IDENTITY);
+ MockLocationProvider mockProvider = new MockLocationProvider(PROPERTIES, PROVIDER_IDENTITY,
+ null);
mockProvider.setAllowed(true);
mManager.setMockProvider(mockProvider);
@@ -441,7 +443,7 @@
@Test
public void testRegisterListener_SameProcess() throws Exception {
CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
- "attribution");
+ "attribution", "listener");
ILocationListener listener = createMockLocationListener();
mManager.registerLocationRequest(
@@ -477,7 +479,7 @@
@Test
public void testRegisterListener_Unregister_SameProcess() throws Exception {
CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
- "attribution");
+ "attribution", "listener");
ILocationListener listener = createMockLocationListener();
mManager.registerLocationRequest(
@@ -604,7 +606,7 @@
@Test
public void testRegisterListener_Wakelock() throws Exception {
CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
- "attribution");
+ "attribution", "listener");
ILocationListener listener = createMockLocationListener();
mManager.registerLocationRequest(
@@ -1047,7 +1049,7 @@
private final ArrayList<Runnable> mFlushCallbacks = new ArrayList<>();
TestProvider(ProviderProperties properties, CallerIdentity identity) {
- super(DIRECT_EXECUTOR, identity, properties);
+ super(DIRECT_EXECUTOR, identity, properties, null);
}
public void setProviderAllowed(boolean allowed) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java
index 07170da..e8a0bb5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/MockableLocationProviderTest.java
@@ -71,7 +71,8 @@
.setPowerUsage(POWER_USAGE_LOW)
.setAccuracy(ACCURACY_FINE)
.build(),
- CallerIdentity.forTest(0, 1, "testpackage", "test"));
+ CallerIdentity.forTest(0, 1, "testpackage", "test"),
+ null);
mProvider = new MockableLocationProvider(lock);
mProvider.getController().setListener(mListener);
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java b/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java
index 775bdd5..a1eadbe 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/test/FakeProvider.java
@@ -40,7 +40,7 @@
private final FakeProviderInterface mFakeInterface;
public FakeProvider(FakeProviderInterface fakeInterface) {
- super(Runnable::run, null, null);
+ super(Runnable::run, null, null, null);
mFakeInterface = fakeInterface;
}
diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
index 1328b91..07f6732 100644
--- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
@@ -110,6 +110,8 @@
UserInfo userInfo = addUser(USER_ID_1);
mAppHibernationService.onUserUnlocking(new SystemService.TargetUser(userInfo));
doReturn(true).when(mUserManager).isUserUnlockingOrUnlocked(USER_ID_1);
+
+ mAppHibernationService.mIsServiceEnabled = true;
}
@Test
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 73b0105..6890ed1 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
@@ -28,6 +28,7 @@
import android.app.appsearch.SetSchemaResponse;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
+import android.util.ArrayMap;
import android.util.ArraySet;
import androidx.test.core.app.ApplicationProvider;
@@ -55,6 +56,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
public class AppSearchImplTest {
@@ -971,21 +973,46 @@
}
@Test
- public void testHasSchemaType() throws Exception {
- // Nothing exists yet
- assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isFalse();
+ public void testGetPackageToDatabases() throws Exception {
+ Map<String, Set<String>> existingMapping = mAppSearchImpl.getPackageToDatabases();
+ Map<String, Set<String>> expectedMapping = new ArrayMap<>();
+ expectedMapping.putAll(existingMapping);
+ // Has database1
+ expectedMapping.put("package1", ImmutableSet.of("database1"));
mAppSearchImpl.setSchema(
- "package",
- "database",
- Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
+ "package1",
+ "database1",
+ Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false);
- assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isTrue();
+ assertThat(mAppSearchImpl.getPackageToDatabases())
+ .containsExactlyEntriesIn(expectedMapping);
- assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "UnknownSchema"))
- .isFalse();
+ // Has both databases
+ expectedMapping.put("package1", ImmutableSet.of("database1", "database2"));
+ mAppSearchImpl.setSchema(
+ "package1",
+ "database2",
+ Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+ assertThat(mAppSearchImpl.getPackageToDatabases())
+ .containsExactlyEntriesIn(expectedMapping);
+
+ // Has both packages
+ expectedMapping.put("package2", ImmutableSet.of("database1"));
+ mAppSearchImpl.setSchema(
+ "package2",
+ "database1",
+ Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false);
+ assertThat(mAppSearchImpl.getPackageToDatabases())
+ .containsExactlyEntriesIn(expectedMapping);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
index b98f025..205ff30 100644
--- a/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
+import android.app.backup.BackupAgent;
import android.app.backup.BackupManager.OperationType;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
@@ -30,6 +31,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import com.android.internal.backup.IBackupTransport;
import android.platform.test.annotations.Presubmit;
import androidx.test.runner.AndroidJUnit4;
@@ -56,6 +58,7 @@
@Mock IBackupObserver mBackupObserver;
@Mock PackageManager mPackageManager;
@Mock TransportClient mTransportClient;
+ @Mock IBackupTransport mBackupTransport;
@Mock BackupEligibilityRules mBackupEligibilityRules;
@@ -132,6 +135,33 @@
assertThat(params.mBackupEligibilityRules).isEqualTo(mBackupEligibilityRules);
}
+ @Test
+ public void testGetOperationTypeFromTransport_returnsBackupByDefault()
+ throws Exception {
+ when(mTransportClient.connectOrThrow(any())).thenReturn(mBackupTransport);
+ when(mBackupTransport.getTransportFlags()).thenReturn(0);
+
+ int operationType = mService.getOperationTypeFromTransport(mTransportClient);
+
+ assertThat(operationType).isEqualTo(OperationType.BACKUP);
+ }
+
+ @Test
+ public void testGetOperationTypeFromTransport_returnsMigrationForMigrationTransport()
+ throws Exception {
+ // This is a temporary flag to control the new behaviour until it's ready to be fully
+ // rolled out.
+ mService.shouldUseNewBackupEligibilityRules = true;
+
+ when(mTransportClient.connectOrThrow(any())).thenReturn(mBackupTransport);
+ when(mBackupTransport.getTransportFlags()).thenReturn(
+ BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER);
+
+ int operationType = mService.getOperationTypeFromTransport(mTransportClient);
+
+ assertThat(operationType).isEqualTo(OperationType.MIGRATION);
+ }
+
private static PackageInfo getPackageInfo(String packageName) {
PackageInfo packageInfo = new PackageInfo();
packageInfo.applicationInfo = new ApplicationInfo();
@@ -141,6 +171,7 @@
private static class TestBackupService extends UserBackupManagerService {
boolean isEnabledStatePersisted = false;
+ boolean shouldUseNewBackupEligibilityRules = false;
TestBackupService(Context context, PackageManager packageManager) {
super(context, packageManager);
@@ -158,5 +189,10 @@
@Override
void updateStateOnBackupEnabled(boolean wasEnabled, boolean enable) {}
+
+ @Override
+ boolean shouldUseNewBackupEligibilityRules() {
+ return shouldUseNewBackupEligibilityRules;
+ }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
index 2cbc3f3..a694d5e 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
@@ -153,4 +153,25 @@
assertEquals("Period not restored", periodic.periodMillis, oneoff.periodMillis);
assertEquals("Flex not restored", periodic.flexMillis, oneoff.flexMillis);
}
+
+ @SmallTest
+ public void testScheduleAsEjIsInExtras() {
+ Account account1 = new Account("account1", "type1");
+ Bundle b1 = new Bundle();
+ b1.putBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB, true);
+
+ SyncOperation op1 = new SyncOperation(account1, 0, 1, "foo", 0,
+ SyncOperation.REASON_USER_START, "authority1", b1, false,
+ ContentResolver.SYNC_EXEMPTION_NONE);
+ assertTrue(op1.isScheduledAsExpeditedJob());
+
+ PersistableBundle pb = op1.toJobInfoExtras();
+ assertTrue("EJ extra not found in job extras",
+ ((PersistableBundle) pb.get("syncExtras"))
+ .containsKey(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB));
+
+ SyncOperation op2 = SyncOperation.maybeCreateFromJobExtras(pb);
+ assertTrue("EJ extra not found in extras", op2.getClonedExtras()
+ .getBoolean(ContentResolver.SYNC_EXTRAS_SCHEDULE_AS_EXPEDITED_JOB));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 6add8d1..87100a6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -20,6 +20,8 @@
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS;
import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID;
@@ -826,7 +828,7 @@
* {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)}
*/
@Test
- public void testForceRemoveActiveAdmin() throws Exception {
+ public void testForceRemoveActiveAdmin_nonShellCaller() throws Exception {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
// Add admin.
@@ -840,8 +842,53 @@
// Calling from a non-shell uid should fail with a SecurityException
mContext.binder.callingUid = 123456;
assertExpectException(SecurityException.class,
- /* messageRegex =*/ "Non-shell user attempted to call",
+ /* messageRegex = */ null,
() -> dpms.forceRemoveActiveAdmin(admin1, CALLER_USER_HANDLE));
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)}
+ */
+ @Test
+ public void testForceRemoveActiveAdmin_nonShellCallerWithPermission() throws Exception {
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // Add admin.
+ setupPackageInPackageManager(admin1.getPackageName(),
+ /* userId= */ CALLER_USER_HANDLE,
+ /* appId= */ 10138,
+ /* flags= */ ApplicationInfo.FLAG_TEST_ONLY);
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+
+ mContext.binder.callingUid = 123456;
+ mContext.callerPermissions.add(
+ android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+ dpms.forceRemoveActiveAdmin(admin1, CALLER_USER_HANDLE);
+
+ mContext.callerPermissions.add(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+ // Verify
+ assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
+ verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
+ null, CALLER_USER_HANDLE);
+ }
+
+ /**
+ * Test for:
+ * {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)}
+ */
+ @Test
+ public void testForceRemoveActiveAdmin_ShellCaller() throws Exception {
+ mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
+
+ // Add admin.
+ setupPackageInPackageManager(admin1.getPackageName(),
+ /* userId= */ CALLER_USER_HANDLE,
+ /* appId= */ 10138,
+ /* flags= */ ApplicationInfo.FLAG_TEST_ONLY);
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
mContext.binder.callingUid = Process.SHELL_UID;
dpms.forceRemoveActiveAdmin(admin1, CALLER_USER_HANDLE);
@@ -7028,6 +7075,71 @@
}
@Test
+ public void testSetDeviceOwnerType_throwsExceptionWhenCallerNotAuthorized() {
+ assertThrows(SecurityException.class,
+ () -> dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_DEFAULT));
+ }
+
+ @Test
+ public void testSetDeviceOwnerType_throwsExceptionWhenThereIsNoDeviceOwner() {
+ mContext.binder.clearCallingIdentity();
+ assertThrows(IllegalStateException.class,
+ () -> dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_DEFAULT));
+ }
+
+ @Test
+ public void testSetDeviceOwnerType_throwsExceptionWhenNotAsDeviceOwnerAdmin() throws Exception {
+ setDeviceOwner();
+
+ assertThrows(IllegalStateException.class,
+ () -> dpm.setDeviceOwnerType(admin2, DEVICE_OWNER_TYPE_FINANCED));
+ }
+
+ @Test
+ public void testSetDeviceOwnerType_asDeviceOwner_toFinancedDevice() throws Exception {
+ setDeviceOwner();
+
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ int returnedDeviceOwnerType = dpm.getDeviceOwnerType(admin1);
+ assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
+ assertThat(returnedDeviceOwnerType).isEqualTo(DEVICE_OWNER_TYPE_FINANCED);
+
+ initializeDpms();
+
+ returnedDeviceOwnerType = dpm.getDeviceOwnerType(admin1);
+ assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
+ assertThat(returnedDeviceOwnerType).isEqualTo(DEVICE_OWNER_TYPE_FINANCED);
+ }
+
+ @Test
+ public void testSetDeviceOwnerType_asDeviceOwner_throwsExceptionWhenSetDeviceOwnerTypeAgain()
+ throws Exception {
+ setDeviceOwner();
+
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ int returnedDeviceOwnerType = dpm.getDeviceOwnerType(admin1);
+ assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
+ assertThat(returnedDeviceOwnerType).isEqualTo(DEVICE_OWNER_TYPE_FINANCED);
+
+ assertThrows(IllegalStateException.class,
+ () -> dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_DEFAULT));
+ }
+
+ @Test
+ public void testGetDeviceOwnerType_throwsExceptionWhenThereIsNoDeviceOwner() {
+ assertThrows(IllegalStateException.class, () -> dpm.getDeviceOwnerType(admin1));
+ }
+
+ @Test
+ public void testGetDeviceOwnerType_throwsExceptionWhenNotAsDeviceOwnerAdmin() throws Exception {
+ setDeviceOwner();
+
+ assertThrows(IllegalStateException.class, () -> dpm.getDeviceOwnerType(admin2));
+ }
+
+ @Test
public void testSetUsbDataSignalingEnabled_noDeviceOwnerOrPoOfOrgOwnedDevice() {
assertThrows(SecurityException.class,
() -> dpm.setUsbDataSignalingEnabled(true));
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index bfe183c..39ca925d 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -16,6 +16,9 @@
package com.android.server.devicepolicy;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
+
import static com.google.common.truth.Truth.assertThat;
import android.content.ComponentName;
@@ -35,7 +38,6 @@
* <p>Run this test with:
*
* {@code atest FrameworksServicesTests:com.android.server.devicepolicy.OwnersTest}
- *
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -67,6 +69,8 @@
assertThat(owners.hasDeviceOwner()).isFalse();
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -75,6 +79,12 @@
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
+
+ owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(),
+ DEVICE_OWNER_TYPE_FINANCED);
+ // There is no device owner, so the default owner type should be returned.
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
}
// Then re-read and check.
@@ -84,6 +94,8 @@
assertThat(owners.hasDeviceOwner()).isFalse();
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -122,6 +134,8 @@
assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -142,6 +156,8 @@
assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getSystemUpdatePolicy()).isNull();
assertThat(owners.getProfileOwnerKeys()).isEmpty();
@@ -180,6 +196,8 @@
assertThat(owners.hasDeviceOwner()).isFalse();
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
assertThat(owners.getSystemUpdatePolicy()).isNull();
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getProfileOwnerKeys()).hasSize(2);
assertThat(owners.getProfileOwnerComponent(10))
@@ -208,6 +226,8 @@
assertThat(owners.hasDeviceOwner()).isFalse();
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
assertThat(owners.getSystemUpdatePolicy()).isNull();
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getProfileOwnerKeys()).hasSize(2);
assertThat(owners.getProfileOwnerComponent(10))
@@ -260,6 +280,8 @@
assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getSystemUpdatePolicy()).isNotNull();
assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
@@ -292,6 +314,8 @@
assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getSystemUpdatePolicy()).isNotNull();
assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
@@ -315,12 +339,21 @@
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
owners.setDeviceOwnerUserRestrictionsMigrated();
+
+ owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(),
+ DEVICE_OWNER_TYPE_FINANCED);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_FINANCED);
}
{
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
+ assertThat(owners.hasDeviceOwner()).isTrue();
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_FINANCED);
+
assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
@@ -328,12 +361,22 @@
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
owners.setProfileOwnerUserRestrictionsMigrated(11);
+
+ owners.setDeviceOwnerType(owners.getDeviceOwnerPackageName(),
+ DEVICE_OWNER_TYPE_DEFAULT);
+ // The previous device owner type should persist.
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_FINANCED);
}
{
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
+ assertThat(owners.hasDeviceOwner()).isTrue();
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_FINANCED);
+
assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
@@ -369,6 +412,8 @@
assertThat(owners.hasDeviceOwner()).isFalse();
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getSystemUpdatePolicy()).isNull();
@@ -388,6 +433,8 @@
assertThat(owners.hasDeviceOwner()).isFalse();
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getSystemUpdatePolicy()).isNull();
@@ -425,6 +472,8 @@
assertThat(owners.hasDeviceOwner()).isFalse();
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getProfileOwnerKeys()).isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNotNull();
@@ -444,6 +493,8 @@
assertThat(owners.hasDeviceOwner()).isFalse();
assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getProfileOwnerKeys()).isEmpty();
assertThat(owners.getSystemUpdatePolicy()).isNotNull();
@@ -472,9 +523,16 @@
assertThat(owners.getLegacyConfigFile().exists()).isFalse();
assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
+ assertThat(owners.getDeviceOwnerType(owners.getDeviceOwnerPackageName())).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
+ String previousDeviceOwnerPackageName = owners.getDeviceOwnerPackageName();
+ owners.setDeviceOwnerType(previousDeviceOwnerPackageName, DEVICE_OWNER_TYPE_FINANCED);
+ assertThat(owners.getDeviceOwnerType(previousDeviceOwnerPackageName)).isEqualTo(
+ DEVICE_OWNER_TYPE_FINANCED);
+
// Then clear all information and save.
owners.clearDeviceOwner();
owners.clearSystemUpdatePolicy();
@@ -491,5 +549,8 @@
assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+
+ assertThat(owners.getDeviceOwnerType(previousDeviceOwnerPackageName)).isEqualTo(
+ DEVICE_OWNER_TYPE_DEFAULT);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index 23a4c2f..54825ee 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -64,7 +64,6 @@
@Mock HysteresisLevels mAmbientBrightnessThresholds;
@Mock HysteresisLevels mScreenBrightnessThresholds;
@Mock Handler mNoOpHandler;
- @Mock DisplayDeviceConfig mDisplayDeviceConfig;
@Mock DisplayDevice mDisplayDevice;
private static final int LIGHT_SENSOR_WARMUP_TIME = 0;
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index f0b4f1b..285806b 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -88,7 +88,9 @@
};
private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f };
- private static final int[] BACKLIGHT_RANGE = { 1, 255 };
+ private static final float[] DISPLAY_LEVELS_RANGE_NITS = { 13.25f, 478.5f };
+ private static final float[] BACKLIGHT_RANGE_ZERO_TO_ONE = { 0.0f, 1.0f };
+ private static final float[] DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT = { 0.03149606299f, 1.0f };
private static final float[] EMPTY_FLOAT_ARRAY = new float[0];
private static final int[] EMPTY_INT_ARRAY = new int[0];
@@ -114,25 +116,28 @@
};
private static final Spline GAMMA_CORRECTION_SPLINE = Spline.createSpline(
new float[] { 0.0f, 100.0f, 1000.0f, 2500.0f, 4000.0f, 4900.0f, 5000.0f },
- new float[] { 0.035f, 0.035f, 0.221f, 0.523f, 0.797f, 0.980f, 1.0f });
+ new float[] { 0.0475f, 0.0475f, 0.2225f, 0.5140f, 0.8056f, 0.9805f, 1.0f });
@Test
public void testSimpleStrategyMappingAtControlPoints() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
- BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res, ddc);
assertNotNull("BrightnessMappingStrategy should not be null", simple);
for (int i = 0; i < LUX_LEVELS.length; i++) {
- final float expectedLevel =
- (float) DISPLAY_LEVELS_BACKLIGHT[i] / PowerManager.BRIGHTNESS_ON;
+ final float expectedLevel = MathUtils.map(PowerManager.BRIGHTNESS_OFF + 1,
+ PowerManager.BRIGHTNESS_ON, PowerManager.BRIGHTNESS_MIN,
+ PowerManager.BRIGHTNESS_MAX, DISPLAY_LEVELS_BACKLIGHT[i]);
assertEquals(expectedLevel,
- simple.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/);
+ simple.getBrightness(LUX_LEVELS[i]), 0.0001f /*tolerance*/);
}
}
@Test
public void testSimpleStrategyMappingBetweenControlPoints() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
- BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy simple = BrightnessMappingStrategy.create(res, ddc);
assertNotNull("BrightnessMappingStrategy should not be null", simple);
for (int i = 1; i < LUX_LEVELS.length; i++) {
final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2;
@@ -146,66 +151,71 @@
@Test
public void testSimpleStrategyIgnoresNewConfiguration() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
- final int N = LUX_LEVELS.length;
final float[] lux = { 0f, 1f };
final float[] nits = { 0, PowerManager.BRIGHTNESS_ON };
BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
.build();
strategy.setBrightnessConfiguration(config);
- assertNotEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
+ assertNotEquals(1.0f, strategy.getBrightness(1f), 0.0001f /*tolerance*/);
}
@Test
public void testSimpleStrategyIgnoresNullConfiguration() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
strategy.setBrightnessConfiguration(null);
final int N = DISPLAY_LEVELS_BACKLIGHT.length;
final float expectedBrightness =
(float) DISPLAY_LEVELS_BACKLIGHT[N - 1] / PowerManager.BRIGHTNESS_ON;
assertEquals(expectedBrightness,
- strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01 /*tolerance*/);
+ strategy.getBrightness(LUX_LEVELS[N - 1]), 0.0001f /*tolerance*/);
}
@Test
public void testPhysicalStrategyMappingAtControlPoints() {
- Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
- DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res);
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
assertNotNull("BrightnessMappingStrategy should not be null", physical);
for (int i = 0; i < LUX_LEVELS.length; i++) {
- final float expectedLevel = DISPLAY_LEVELS_NITS[i] / DISPLAY_RANGE_NITS[1];
+ final float expectedLevel = MathUtils.map(DISPLAY_RANGE_NITS[0], DISPLAY_RANGE_NITS[1],
+ DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT[0],
+ DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT[1],
+ DISPLAY_LEVELS_NITS[i]);
assertEquals(expectedLevel,
- physical.getBrightness(LUX_LEVELS[i]), 0.01f /*tolerance*/);
+ physical.getBrightness(LUX_LEVELS[i]),
+ 0.0001f /*tolerance*/);
}
}
@Test
public void testPhysicalStrategyMappingBetweenControlPoints() {
- Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
- DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res);
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE);
+ BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
assertNotNull("BrightnessMappingStrategy should not be null", physical);
- Spline backlightToBrightness =
- Spline.createSpline(toFloatArray(BACKLIGHT_RANGE), DISPLAY_RANGE_NITS);
+ Spline brightnessToNits =
+ Spline.createSpline(BACKLIGHT_RANGE_ZERO_TO_ONE, DISPLAY_RANGE_NITS);
for (int i = 1; i < LUX_LEVELS.length; i++) {
- final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2;
- final float backlight = physical.getBrightness(lux) * PowerManager.BRIGHTNESS_ON;
- final float nits = backlightToBrightness.interpolate(backlight);
- assertTrue("Desired brightness should be between adjacent control points.",
+ final float lux = (LUX_LEVELS[i - 1] + LUX_LEVELS[i]) / 2.0f;
+ final float brightness = physical.getBrightness(lux);
+ final float nits = brightnessToNits.interpolate(brightness);
+ assertTrue("Desired brightness should be between adjacent control points: " + nits,
nits > DISPLAY_LEVELS_NITS[i - 1] && nits < DISPLAY_LEVELS_NITS[i]);
}
}
@Test
public void testPhysicalStrategyUsesNewConfigurations() {
- Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
- DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
final float[] lux = { 0f, 1f };
final float[] nits = {
@@ -216,46 +226,53 @@
BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
.build();
strategy.setBrightnessConfiguration(config);
- assertEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
+ assertEquals(1.0f, strategy.getBrightness(1f), 0.0001f /*tolerance*/);
// Check that null returns us to the default configuration.
strategy.setBrightnessConfiguration(null);
final int N = DISPLAY_LEVELS_NITS.length;
final float expectedBrightness = DISPLAY_LEVELS_NITS[N - 1] / DISPLAY_RANGE_NITS[1];
assertEquals(expectedBrightness,
- strategy.getBrightness(LUX_LEVELS[N - 1]), 0.01f /*tolerance*/);
+ strategy.getBrightness(LUX_LEVELS[N - 1]), 0.0001f /*tolerance*/);
}
@Test
public void testPhysicalStrategyRecalculateSplines() {
- Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS,
- BACKLIGHT_RANGE);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+ Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS);
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
float[] adjustedNits50p = new float[DISPLAY_RANGE_NITS.length];
for (int i = 0; i < DISPLAY_RANGE_NITS.length; i++) {
adjustedNits50p[i] = DISPLAY_RANGE_NITS[i] * 0.5f;
}
// Default is unadjusted
- assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
- assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+ assertEquals(DISPLAY_RANGE_NITS[0], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]),
+ 0.0001f /* tolerance */);
+ assertEquals(DISPLAY_RANGE_NITS[1], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]),
+ 0.0001f /* tolerance */);
// When adjustment is turned on, adjustment array is used
strategy.recalculateSplines(true, adjustedNits50p);
- assertEquals(1.3425f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
- assertEquals(239.25f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+ assertEquals(DISPLAY_RANGE_NITS[0] / 2,
+ strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]), 0.0001f /* tolerance */);
+ assertEquals(DISPLAY_RANGE_NITS[1] / 2,
+ strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]), 0.0001f /* tolerance */);
// When adjustment is turned off, adjustment array is ignored
strategy.recalculateSplines(false, adjustedNits50p);
- assertEquals(2.685f, strategy.convertToNits(BACKLIGHT_RANGE[0]), 0.01f /* tolerance */);
- assertEquals(478.5f, strategy.convertToNits(BACKLIGHT_RANGE[1]), 0.01f /* tolerance */);
+ assertEquals(DISPLAY_RANGE_NITS[0], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[0]),
+ 0.0001f /* tolerance */);
+ assertEquals(DISPLAY_RANGE_NITS[1], strategy.convertToNits(BACKLIGHT_RANGE_ZERO_TO_ONE[1]),
+ 0.0001f /* tolerance */);
}
@Test
public void testDefaultStrategyIsPhysical() {
Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT,
- DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+ DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
assertTrue(strategy instanceof BrightnessMappingStrategy.PhysicalMappingStrategy);
}
@@ -266,15 +283,15 @@
int tmp = lux[idx];
lux[idx] = lux[idx+1];
lux[idx+1] = tmp;
- Resources res = createResources(lux, DISPLAY_LEVELS_NITS,
- DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+ Resources res = createResources(lux, DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy);
// And make sure we get the same result even if it's monotone but not increasing.
lux[idx] = lux[idx+1];
- res = createResources(lux, DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- strategy = BrightnessMappingStrategy.create(res);
+ res = createResources(lux, DISPLAY_LEVELS_NITS);
+ strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy);
}
@@ -285,13 +302,13 @@
// Make sure it's strictly increasing so that the only failure is the differing array
// lengths
lux[lux.length - 1] = lux[lux.length - 2] + 1;
- Resources res = createResources(lux, DISPLAY_LEVELS_NITS,
- DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res);
+ Resources res = createResources(lux, DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy);
res = createResources(lux, DISPLAY_LEVELS_BACKLIGHT);
- strategy = BrightnessMappingStrategy.create(res);
+ strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy);
// Extra backlight level
@@ -299,43 +316,45 @@
DISPLAY_LEVELS_BACKLIGHT, DISPLAY_LEVELS_BACKLIGHT.length+1);
backlight[backlight.length - 1] = backlight[backlight.length - 2] + 1;
res = createResources(LUX_LEVELS, backlight);
- strategy = BrightnessMappingStrategy.create(res);
+ strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy);
// Extra nits level
final float[] nits = Arrays.copyOf(DISPLAY_RANGE_NITS, DISPLAY_LEVELS_NITS.length+1);
nits[nits.length - 1] = nits[nits.length - 2] + 1;
- res = createResources(LUX_LEVELS, nits, DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- strategy = BrightnessMappingStrategy.create(res);
+ res = createResources(LUX_LEVELS, nits);
+ strategy = BrightnessMappingStrategy.create(res, ddc);
assertNull(strategy);
}
@Test
public void testPhysicalStrategyRequiresNitsMapping() {
Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
- DISPLAY_LEVELS_NITS, EMPTY_FLOAT_ARRAY /*nitsRange*/, BACKLIGHT_RANGE);
- BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res);
+ DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc(EMPTY_FLOAT_ARRAY /*nitsRange*/);
+ BrightnessMappingStrategy physical = BrightnessMappingStrategy.create(res, ddc);
assertNull(physical);
res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
- DISPLAY_LEVELS_NITS, DISPLAY_RANGE_NITS, EMPTY_INT_ARRAY /*backlightRange*/);
- physical = BrightnessMappingStrategy.create(res);
+ DISPLAY_LEVELS_NITS);
+ physical = BrightnessMappingStrategy.create(res, ddc);
assertNull(physical);
res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
- DISPLAY_LEVELS_NITS, EMPTY_FLOAT_ARRAY /*nitsRange*/,
- EMPTY_INT_ARRAY /*backlightRange*/);
- physical = BrightnessMappingStrategy.create(res);
+ DISPLAY_LEVELS_NITS);
+ physical = BrightnessMappingStrategy.create(res, ddc);
assertNull(physical);
}
@Test
public void testStrategiesAdaptToUserDataPoint() {
- Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_NITS,
- DISPLAY_RANGE_NITS, BACKLIGHT_RANGE);
- assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res));
+ Resources res = createResources(LUX_LEVELS, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
+ DISPLAY_LEVELS_NITS);
+ DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE);
+ assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc));
+ ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE);
res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
- assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res));
+ assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc));
}
private static void assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy strategy) {
@@ -351,7 +370,7 @@
// Then make sure that all control points after the middle lux level are also set to max...
for (int i = idx; i < LUX_LEVELS.length; i++) {
- assertEquals(strategy.getBrightness(LUX_LEVELS[idx]), 1.0, 0.01 /*tolerance*/);
+ assertEquals(strategy.getBrightness(LUX_LEVELS[idx]), 1.0, 0.0001f /*tolerance*/);
}
// ...and that all control points before the middle lux level are strictly less than the
@@ -369,12 +388,12 @@
strategy.clearUserDataPoints();
for (int i = 0; i < LUX_LEVELS.length; i++) {
assertEquals(initialBrightnessLevels[i], strategy.getBrightness(LUX_LEVELS[i]),
- 0.01 /*tolerance*/);
+ 0.0001f /*tolerance*/);
}
// Now set the middle of the lux range to something just above the minimum.
float minBrightness = strategy.getBrightness(LUX_LEVELS[0]);
- strategy.addUserDataPoint(LUX_LEVELS[idx], minBrightness + 0.01f);
+ strategy.addUserDataPoint(LUX_LEVELS[idx], minBrightness + 0.0001f);
// Then make sure the curve is still monotonic.
prevBrightness = 0f;
@@ -389,31 +408,21 @@
// be true assuming that there are more than two lux levels in the curve since we picked a
// brightness just barely above the minimum for the middle of the curve.
minBrightness = (float) MathUtils.pow(minBrightness, MAXIMUM_GAMMA); // Gamma correction.
- assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.01 /*tolerance*/);
- }
-
- private static float[] toFloatArray(int[] vals) {
- float[] newVals = new float[vals.length];
- for (int i = 0; i < vals.length; i++) {
- newVals[i] = (float) vals[i];
- }
- return newVals;
+ assertEquals(minBrightness, strategy.getBrightness(LUX_LEVELS[0]), 0.0001f /*tolerance*/);
}
private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight) {
return createResources(luxLevels, brightnessLevelsBacklight,
- EMPTY_FLOAT_ARRAY /*brightnessLevelsNits*/, EMPTY_FLOAT_ARRAY /*nitsRange*/,
- EMPTY_INT_ARRAY /*backlightRange*/);
+ EMPTY_FLOAT_ARRAY /*brightnessLevelsNits*/);
}
- private Resources createResources(int[] luxLevels, float[] brightnessLevelsNits,
- float[] nitsRange, int[] backlightRange) {
+ private Resources createResources(int[] luxLevels, float[] brightnessLevelsNits) {
return createResources(luxLevels, EMPTY_INT_ARRAY /*brightnessLevelsBacklight*/,
- brightnessLevelsNits, nitsRange, backlightRange);
+ brightnessLevelsNits);
}
private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight,
- float[] brightnessLevelsNits, float[] nitsRange, int[] backlightRange) {
+ float[] brightnessLevelsNits) {
Resources mockResources = mock(Resources.class);
// For historical reasons, the lux levels resource implicitly defines the first point as 0,
// so we need to chop it off of the array the mock resource object returns.
@@ -430,15 +439,6 @@
com.android.internal.R.array.config_autoBrightnessDisplayValuesNits))
.thenReturn(mockBrightnessLevelNits);
- TypedArray mockNitsRange = createFloatTypedArray(nitsRange);
- when(mockResources.obtainTypedArray(
- com.android.internal.R.array.config_screenBrightnessNits))
- .thenReturn(mockNitsRange);
-
- when(mockResources.getIntArray(
- com.android.internal.R.array.config_screenBrightnessBacklight))
- .thenReturn(backlightRange);
-
when(mockResources.getInteger(
com.android.internal.R.integer.config_screenBrightnessSettingMinimum))
.thenReturn(1);
@@ -451,6 +451,21 @@
return mockResources;
}
+ private DisplayDeviceConfig createDdc() {
+ return createDdc(DISPLAY_RANGE_NITS);
+ }
+
+ private DisplayDeviceConfig createDdc(float[] nitsArray) {
+ return createDdc(nitsArray, DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT);
+ }
+
+ private DisplayDeviceConfig createDdc(float[] nitsArray, float[] backlightArray) {
+ DisplayDeviceConfig mockDdc = mock(DisplayDeviceConfig.class);
+ when(mockDdc.getNits()).thenReturn(nitsArray);
+ when(mockDdc.getBrightness()).thenReturn(backlightArray);
+ return mockDdc;
+ }
+
private TypedArray createFloatTypedArray(float[] vals) {
TypedArray mockArray = mock(TypedArray.class);
when(mockArray.length()).thenAnswer(invocation -> {
@@ -488,21 +503,22 @@
final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1);
final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3);
- Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
- DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources);
+
+ Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
// Let's start with a validity check:
- assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */);
- assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */);
- assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */);
+ assertEquals(y1, strategy.getBrightness(x1), 0.0001f /* tolerance */);
+ assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
+ assertEquals(y3, strategy.getBrightness(x3), 0.0001f /* tolerance */);
// OK, let's roll:
float gamma = 0.5f;
strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma));
- assertEquals(MathUtils.pow(y1, gamma), strategy.getBrightness(x1), 0.01f /* tolerance */);
- assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */);
- assertEquals(MathUtils.pow(y3, gamma), strategy.getBrightness(x3), 0.01f /* tolerance */);
- // The adjustment should be +0.63 (manual calculation).
- assertEquals(+0.63f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+ assertEquals(MathUtils.pow(y1, gamma), strategy.getBrightness(x1), 0.0001f /* tolerance */);
+ assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
+ assertEquals(MathUtils.pow(y3, gamma), strategy.getBrightness(x3), 0.0001f /* tolerance */);
+ // The adjustment should be +0.6308 (manual calculation).
+ assertEquals(+0.6308f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
}
@Test
@@ -516,39 +532,39 @@
final float y1 = GAMMA_CORRECTION_SPLINE.interpolate(x1);
final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
final float y3 = GAMMA_CORRECTION_SPLINE.interpolate(x3);
- Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
- DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources);
+ Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
// Validity check:
- assertEquals(y1, strategy.getBrightness(x1), 0.01f /* tolerance */);
- assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */);
- assertEquals(y3, strategy.getBrightness(x3), 0.01f /* tolerance */);
+ assertEquals(y1, strategy.getBrightness(x1), 0.0001f /* tolerance */);
+ assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
+ assertEquals(y3, strategy.getBrightness(x3), 0.0001f /* tolerance */);
// Let's roll:
float gamma = 0.25f;
final float minGamma = 1.0f / MAXIMUM_GAMMA;
strategy.addUserDataPoint(x2, (float) MathUtils.pow(y2, gamma));
- assertEquals(MathUtils.pow(y1, minGamma), strategy.getBrightness(x1),
- 0.01f /* tolerance */);
- assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2),
- 0.01f /* tolerance */);
- assertEquals(MathUtils.pow(y3, minGamma), strategy.getBrightness(x3),
- 0.01f /* tolerance */);
+ assertEquals(MathUtils.pow(y1, minGamma),
+ strategy.getBrightness(x1), 0.0001f /* tolerance */);
+ assertEquals(MathUtils.pow(y2, gamma),
+ strategy.getBrightness(x2), 0.0001f /* tolerance */);
+ assertEquals(MathUtils.pow(y3, minGamma),
+ strategy.getBrightness(x3), 0.0001f /* tolerance */);
// The adjustment should be +1.0 (maximum adjustment).
- assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+ assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
}
@Test
public void testGammaCorrectionExtremeChangeAtCenter() {
// Extreme changes (e.g. setting brightness to 0.0 or 1.0) can't be gamma corrected, so we
// just make sure the adjustment reflects the change.
- Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
- DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources);
- assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+ Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
+ assertEquals(0.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
strategy.addUserDataPoint(2500, 1.0f);
- assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+ assertEquals(+1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
strategy.addUserDataPoint(2500, 0.0f);
- assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+ assertEquals(-1.0f, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
}
@Test
@@ -562,28 +578,28 @@
final float y0 = GAMMA_CORRECTION_SPLINE.interpolate(x0);
final float y2 = GAMMA_CORRECTION_SPLINE.interpolate(x2);
final float y4 = GAMMA_CORRECTION_SPLINE.interpolate(x4);
- Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS,
- DISPLAY_LEVELS_NITS, DISPLAY_LEVELS_BACKLIGHT);
- BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources);
+ Resources resources = createResources(GAMMA_CORRECTION_LUX, GAMMA_CORRECTION_NITS);
+ DisplayDeviceConfig ddc = createDdc();
+ BrightnessMappingStrategy strategy = BrightnessMappingStrategy.create(resources, ddc);
// Validity, as per tradition:
- assertEquals(y0, strategy.getBrightness(x0), 0.01f /* tolerance */);
- assertEquals(y2, strategy.getBrightness(x2), 0.01f /* tolerance */);
- assertEquals(y4, strategy.getBrightness(x4), 0.01f /* tolerance */);
+ assertEquals(y0, strategy.getBrightness(x0), 0.0001f /* tolerance */);
+ assertEquals(y2, strategy.getBrightness(x2), 0.0001f /* tolerance */);
+ assertEquals(y4, strategy.getBrightness(x4), 0.0001f /* tolerance */);
// Rollin':
float adjustment = 0.3f;
float gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
strategy.addUserDataPoint(x0, y0 + adjustment);
- assertEquals(y0 + adjustment, strategy.getBrightness(x0), 0.01f /* tolerance */);
- assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */);
- assertEquals(MathUtils.pow(y4, gamma), strategy.getBrightness(x4), 0.01f /* tolerance */);
- assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+ assertEquals(y0 + adjustment, strategy.getBrightness(x0), 0.0001f /* tolerance */);
+ assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
+ assertEquals(MathUtils.pow(y4, gamma), strategy.getBrightness(x4), 0.0001f /* tolerance */);
+ assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
// Similarly, if we set a user data point at (x4, 1.0), the adjustment should be 1 - y4.
adjustment = 1.0f - y4;
gamma = (float) MathUtils.pow(MAXIMUM_GAMMA, -adjustment);
strategy.addUserDataPoint(x4, 1.0f);
- assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.01f /* tolerance */);
- assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.01f /* tolerance */);
- assertEquals(1.0f, strategy.getBrightness(x4), 0.01f /* tolerance */);
- assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.01f /* tolerance */);
+ assertEquals(MathUtils.pow(y0, gamma), strategy.getBrightness(x0), 0.0001f /* tolerance */);
+ assertEquals(MathUtils.pow(y2, gamma), strategy.getBrightness(x2), 0.0001f /* tolerance */);
+ assertEquals(1.0f, strategy.getBrightness(x4), 0.0001f /* tolerance */);
+ assertEquals(adjustment, strategy.getAutoBrightnessAdjustment(), 0.0001f /* tolerance */);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 7d7af03..74bf4f5 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -115,7 +115,6 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicy;
-import android.net.NetworkPolicyManager;
import android.net.NetworkState;
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
@@ -386,8 +385,7 @@
Log.d(TAG, "set mUidObserver to " + mUidObserver);
return null;
}
- }).when(mActivityManager).registerUidObserver(any(), anyInt(),
- eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), any(String.class));
+ }).when(mActivityManager).registerUidObserver(any(), anyInt(), anyInt(), any(String.class));
mFutureIntent = newRestrictBackgroundChangedFuture();
mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index ff43da6..ee0a16a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -86,6 +86,7 @@
private TestData mBarUser0DelegateLastClassLoader;
private TestData mSystemServerJar;
+ private TestData mSystemServerJarUpdatedContext;
private TestData mSystemServerJarInvalid;
private int mUser0;
@@ -113,6 +114,8 @@
mSystemServerJar = new TestData("android", isa, mUser0, PATH_CLASS_LOADER_NAME);
mSystemServerJarInvalid = new TestData("android", isa, mUser0, PATH_CLASS_LOADER_NAME);
+ mSystemServerJarUpdatedContext = new TestData("android", isa, mUser0,
+ DELEGATE_LAST_CLASS_LOADER_NAME);
mDexManager = new DexManager(/*Context*/ null, mPM, /*PackageDexOptimizer*/ null,
mInstaller, mInstallLock);
@@ -522,6 +525,24 @@
}
@Test
+ public void testSystemServerOverwritesContext() {
+ // Record bar secondaries with the default PathClassLoader.
+ List<String> secondaries = mSystemServerJar.getSecondaryDexPaths();
+
+ notifyDexLoad(mSystemServerJar, secondaries, mUser0);
+ PackageUseInfo pui = getPackageUseInfo(mSystemServerJar);
+ assertSecondaryUse(mSystemServerJar, pui, secondaries, /*isUsedByOtherApps*/false, mUser0);
+
+ // Record bar secondaries again with a different class loader. This will change the context.
+ notifyDexLoad(mSystemServerJarUpdatedContext, secondaries, mUser0);
+
+ pui = getPackageUseInfo(mSystemServerJar);
+ // We expect that all the contexts to be updated according to the last notify.
+ assertSecondaryUse(mSystemServerJarUpdatedContext, pui, secondaries,
+ /*isUsedByOtherApps*/false, mUser0);
+ }
+
+ @Test
public void testNotifyUnsupportedClassLoaderDoesNotChangeExisting() {
List<String> secondaries = mBarUser0.getSecondaryDexPaths();
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS b/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS
new file mode 100644
index 0000000..66ef75d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/dex/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index adf4551..3450710 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -451,7 +451,7 @@
"PCL[new_context.dex]");
assertTrue(record(fooSecondary1User0NewContext));
- // Not check that the context was switch to variable.
+ // Now check that the context was switch to variable.
TestData expectedContext = mFooSecondary1User0.updateClassLoaderContext(
PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT);
@@ -461,6 +461,22 @@
}
@Test
+ public void testRecordClassLoaderContextOverwritten() {
+ // Record a secondary dex file.
+ assertTrue(record(mFooSecondary1User0));
+ // Now update its context.
+ TestData fooSecondary1User0NewContext = mFooSecondary1User0.updateClassLoaderContext(
+ "PCL[new_context.dex]", true);
+ assertTrue(record(fooSecondary1User0NewContext));
+
+ // Now check that the context was overwritten.
+ TestData expectedContext = mFooSecondary1User0.updateClassLoaderContext(
+ "PCL[new_context.dex]", true);
+
+ assertPackageDexUsage(null, expectedContext);
+ }
+
+ @Test
public void testDexUsageClassLoaderContext() {
final boolean isUsedByOtherApps = false;
final int userId = 0;
@@ -642,8 +658,9 @@
private boolean record(TestData testData) {
return mPackageDexUsage.record(testData.mPackageName, testData.mDexFile,
- testData.mOwnerUserId, testData.mLoaderIsa,
- testData.mPrimaryOrSplit, testData.mUsedBy, testData.mClassLoaderContext);
+ testData.mOwnerUserId, testData.mLoaderIsa,
+ testData.mPrimaryOrSplit, testData.mUsedBy, testData.mClassLoaderContext,
+ testData.mOverwriteCLC);
}
private boolean record(PackageDexUsage packageDexUsage, TestData testData, Set<String> users) {
@@ -651,7 +668,8 @@
for (String user : users) {
result = result && packageDexUsage.record(testData.mPackageName, testData.mDexFile,
testData.mOwnerUserId, testData.mLoaderIsa,
- testData.mPrimaryOrSplit, user, testData.mClassLoaderContext);
+ testData.mPrimaryOrSplit, user, testData.mClassLoaderContext,
+ testData.mOverwriteCLC);
}
return result;
}
@@ -682,15 +700,16 @@
private final boolean mPrimaryOrSplit;
private final String mUsedBy;
private final String mClassLoaderContext;
+ private final boolean mOverwriteCLC;
private TestData(String packageName, String dexFile, int ownerUserId,
String loaderIsa, boolean primaryOrSplit, String usedBy) {
this(packageName, dexFile, ownerUserId, loaderIsa, primaryOrSplit,
- usedBy, "PCL[" + dexFile + "]");
+ usedBy, "PCL[" + dexFile + "]", false);
}
private TestData(String packageName, String dexFile, int ownerUserId,
String loaderIsa, boolean primaryOrSplit, String usedBy,
- String classLoaderContext) {
+ String classLoaderContext, boolean overwriteCLC) {
mPackageName = packageName;
mDexFile = dexFile;
mOwnerUserId = ownerUserId;
@@ -698,16 +717,21 @@
mPrimaryOrSplit = primaryOrSplit;
mUsedBy = usedBy;
mClassLoaderContext = classLoaderContext;
+ mOverwriteCLC = overwriteCLC;
}
private TestData updateClassLoaderContext(String newContext) {
+ return updateClassLoaderContext(newContext, mOverwriteCLC);
+ }
+
+ private TestData updateClassLoaderContext(String newContext, boolean overwriteCLC) {
return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa,
- mPrimaryOrSplit, mUsedBy, newContext);
+ mPrimaryOrSplit, mUsedBy, newContext, overwriteCLC);
}
private TestData updateUsedBy(String newUsedBy) {
return new TestData(mPackageName, mDexFile, mOwnerUserId, mLoaderIsa,
- mPrimaryOrSplit, newUsedBy, mClassLoaderContext);
+ mPrimaryOrSplit, newUsedBy, mClassLoaderContext, mOverwriteCLC);
}
private boolean isUsedByOtherApps() {
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
index 682a80c..5d27552 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
@@ -46,8 +46,8 @@
public void test_unrestricted() {
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
.setUserConfigAllowed(true)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
.setGeoDetectionEnabled(true)
@@ -108,8 +108,8 @@
public void test_restricted() {
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
.setUserConfigAllowed(false)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
.setGeoDetectionEnabled(true)
@@ -170,8 +170,8 @@
public void test_autoDetectNotSupported() {
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
.setUserConfigAllowed(true)
- .setAutoDetectionSupported(false)
- .setGeoDetectionSupported(false)
+ .setAutoDetectionFeatureSupported(false)
+ .setGeoDetectionFeatureSupported(false)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
.setGeoDetectionEnabled(true)
@@ -232,8 +232,8 @@
public void test_geoDetectNotSupported() {
ConfigurationInternal baseConfig = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
.setUserConfigAllowed(true)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(false)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(false)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
.setGeoDetectionEnabled(true)
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
index d2452ea..14e0bbd 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -364,8 +364,8 @@
// the tests.
final boolean geoDetectionEnabled = autoDetectionEnabled;
return new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setUserConfigAllowed(true)
.setAutoDetectionEnabled(autoDetectionEnabled)
.setLocationEnabled(geoDetectionEnabled)
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index c8dba5f..f1f8b2f 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -90,8 +90,8 @@
private static final ConfigurationInternal CONFIG_INT_USER_RESTRICTED_AUTO_DISABLED =
new ConfigurationInternal.Builder(USER_ID)
.setUserConfigAllowed(false)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setAutoDetectionEnabled(false)
.setLocationEnabled(true)
.setGeoDetectionEnabled(false)
@@ -100,8 +100,8 @@
private static final ConfigurationInternal CONFIG_INT_USER_RESTRICTED_AUTO_ENABLED =
new ConfigurationInternal.Builder(USER_ID)
.setUserConfigAllowed(false)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
.setGeoDetectionEnabled(true)
@@ -110,8 +110,8 @@
private static final ConfigurationInternal CONFIG_INT_AUTO_DETECT_NOT_SUPPORTED =
new ConfigurationInternal.Builder(USER_ID)
.setUserConfigAllowed(true)
- .setAutoDetectionSupported(false)
- .setGeoDetectionSupported(false)
+ .setAutoDetectionFeatureSupported(false)
+ .setGeoDetectionFeatureSupported(false)
.setAutoDetectionEnabled(false)
.setLocationEnabled(true)
.setGeoDetectionEnabled(false)
@@ -120,8 +120,8 @@
private static final ConfigurationInternal CONFIG_INT_AUTO_SUPPORTED_GEO_NOT_SUPPORTED =
new ConfigurationInternal.Builder(USER_ID)
.setUserConfigAllowed(true)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(false)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(false)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
.setGeoDetectionEnabled(true)
@@ -130,8 +130,8 @@
private static final ConfigurationInternal CONFIG_INT_AUTO_DISABLED_GEO_DISABLED =
new ConfigurationInternal.Builder(USER_ID)
.setUserConfigAllowed(true)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setAutoDetectionEnabled(false)
.setLocationEnabled(true)
.setGeoDetectionEnabled(false)
@@ -139,8 +139,8 @@
private static final ConfigurationInternal CONFIG_INT_AUTO_ENABLED_GEO_DISABLED =
new ConfigurationInternal.Builder(USER_ID)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setUserConfigAllowed(true)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
@@ -149,8 +149,8 @@
private static final ConfigurationInternal CONFIG_INT_AUTO_ENABLED_GEO_ENABLED =
new ConfigurationInternal.Builder(USER_ID)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setUserConfigAllowed(true)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
index d319488..8280cdc 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
@@ -44,8 +44,8 @@
@UserIdInt int userId, boolean geoDetectionEnabled) {
return new ConfigurationInternal.Builder(userId)
.setUserConfigAllowed(true)
- .setAutoDetectionSupported(true)
- .setGeoDetectionSupported(true)
+ .setAutoDetectionFeatureSupported(true)
+ .setGeoDetectionFeatureSupported(true)
.setAutoDetectionEnabled(true)
.setLocationEnabled(true)
.setGeoDetectionEnabled(geoDetectionEnabled)
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 a640509..cebdbbe 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3671,8 +3671,8 @@
mService.addNotification(r);
final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
- mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
- r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
+ mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(),
+ r.getKey(), NotificationStats.DISMISSAL_AOD,
NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
waitForIdle();
@@ -3694,8 +3694,8 @@
mService.addNotification(r);
final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
- mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getSbn().getTag(),
- r.getSbn().getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
+ mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.getUserId(),
+ r.getKey(), NotificationStats.DISMISSAL_AOD,
NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
waitForIdle();
@@ -6693,8 +6693,7 @@
final NotificationVisibility nv = NotificationVisibility.obtain(nrSummary.getKey(), 1, 2,
true);
mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG,
- nrSummary.getSbn().getTag(),
- nrSummary.getSbn().getId(), nrSummary.getUserId(), nrSummary.getKey(),
+ nrSummary.getUserId(), nrSummary.getKey(),
NotificationStats.DISMISSAL_SHADE,
NotificationStats.DISMISS_SENTIMENT_NEUTRAL, nv);
waitForIdle();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index d13e4dc..7df17fd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -38,6 +38,7 @@
import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS;
import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature;
+import static com.android.server.wm.DisplayAreaPolicyBuilder.KEY_ROOT_DISPLAY_AREA_ID;
import static com.google.common.truth.Truth.assertThat;
@@ -595,6 +596,17 @@
assertThat(token.isDescendantOf(mRoot)).isTrue();
assertThat(token.isDescendantOf(mGroupRoot1)).isFalse();
assertThat(token.isDescendantOf(mGroupRoot2)).isFalse();
+
+ // When the window has options for target root id, attach it to the target root.
+ final Bundle options = new Bundle();
+ options.putInt(KEY_ROOT_DISPLAY_AREA_ID, mGroupRoot2.mFeatureId);
+ final WindowToken token2 = new WindowToken(mWms, mock(IBinder.class),
+ TYPE_STATUS_BAR, true /* persistOnEmpty */, mDisplayContent,
+ true /* ownerCanManageAppTokens */, false /* roundedCornerOverlay */,
+ false /* fromClientToken */, options);
+ policy.addWindow(token2);
+
+ assertThat(token2.isDescendantOf(mGroupRoot2)).isTrue();
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index dc702e6..137cf65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -33,6 +33,7 @@
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -1443,7 +1444,7 @@
// Assume the animation of PipTaskOrganizer is done and then commit fullscreen to task.
pinnedTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
displayContent.continueUpdateOrientationForDiffOrienLaunchingApp();
- assertFalse(displayContent.getPinnedStackController().isPipActiveOrWindowingModeChanging());
+ assertFalse(displayContent.getPinnedTaskController().isPipActiveOrWindowingModeChanging());
assertEquals(pinnedConfigOrientation, displayConfig.orientation);
clearInvocations(mWm);
@@ -1454,7 +1455,7 @@
assertFalse(displayContent.hasTopFixedRotationLaunchingApp());
verify(mWm, atLeastOnce()).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
assertEquals(homeConfigOrientation, displayConfig.orientation);
- assertTrue(displayContent.getPinnedStackController().isPipActiveOrWindowingModeChanging());
+ assertTrue(displayContent.getPinnedTaskController().isPipActiveOrWindowingModeChanging());
}
@Test
@@ -1845,6 +1846,37 @@
verify(t).show(mDisplayContent.mImeScreenshot);
}
+ @Test
+ public void testRotateBounds_keepSamePhysicalPosition() {
+ final DisplayContent dc =
+ new TestDisplayContent.Builder(mAtm, 1000, 2000).build();
+ final Rect initBounds = new Rect(0, 0, 700, 1500);
+ final Rect rotateBounds = new Rect(initBounds);
+
+ // Rotate from 0 to 0
+ dc.rotateBounds(ROTATION_0, ROTATION_0, rotateBounds);
+
+ assertEquals(new Rect(0, 0, 700, 1500), rotateBounds);
+
+ // Rotate from 0 to 90
+ rotateBounds.set(initBounds);
+ dc.rotateBounds(ROTATION_0, ROTATION_90, rotateBounds);
+
+ assertEquals(new Rect(0, 300, 1500, 1000), rotateBounds);
+
+ // Rotate from 0 to 180
+ rotateBounds.set(initBounds);
+ dc.rotateBounds(ROTATION_0, ROTATION_180, rotateBounds);
+
+ assertEquals(new Rect(300, 500, 1000, 2000), rotateBounds);
+
+ // Rotate from 0 to 270
+ rotateBounds.set(initBounds);
+ dc.rotateBounds(ROTATION_0, ROTATION_270, rotateBounds);
+
+ assertEquals(new Rect(500, 0, 2000, 700), rotateBounds);
+ }
+
private boolean isOptionsPanelAtRight(int displayId) {
return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
}
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 8969695..51aec65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -251,7 +251,7 @@
// Simulate the window is in split screen primary stack and the current state is
// minimized and home stack is resizable, so that we should ignore input for the stack.
- final DockedStackDividerController controller =
+ final DockedTaskDividerController controller =
mDisplayContent.getDockedDividerController();
final Task stack = createTaskStackOnDisplay(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
ACTIVITY_TYPE_STANDARD, mDisplayContent);
diff --git a/services/texttospeech/Android.bp b/services/texttospeech/Android.bp
index bacc932..391ab89 100644
--- a/services/texttospeech/Android.bp
+++ b/services/texttospeech/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "services.texttospeech-sources",
srcs: ["java/**/*.java"],
@@ -10,4 +19,4 @@
defaults: ["platform_service_defaults"],
srcs: [":services.texttospeech-sources"],
libs: ["services.core"],
-}
\ No newline at end of file
+}
diff --git a/services/translation/Android.bp b/services/translation/Android.bp
index 804a617..f257f1b 100644
--- a/services/translation/Android.bp
+++ b/services/translation/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "services.translation-sources",
srcs: ["java/**/*.java"],
@@ -10,4 +19,4 @@
defaults: ["platform_service_defaults"],
srcs: [":services.translation-sources"],
libs: ["services.core"],
-}
\ No newline at end of file
+}
diff --git a/telecomm/java/android/telecom/Connection.aidl b/telecomm/java/android/telecom/Connection.aidl
new file mode 100644
index 0000000..5b40036
--- /dev/null
+++ b/telecomm/java/android/telecom/Connection.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.telecom;
+
+/**
+ * {@hide}
+ */
+parcelable Connection.CallFilteringCompletionInfo;
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 942a54e..7c6253ce 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -29,6 +29,7 @@
import android.app.Notification;
import android.bluetooth.BluetoothDevice;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
import android.content.Intent;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
@@ -38,7 +39,9 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
import android.telephony.ims.ImsStreamMediaProfile;
@@ -3379,6 +3382,121 @@
public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {}
/**
+ * Information provided to a {@link Connection} upon completion of call filtering in Telecom.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final class CallFilteringCompletionInfo implements Parcelable {
+ private final boolean mIsBlocked;
+ private final boolean mIsInContacts;
+ private final CallScreeningService.CallResponse mCallResponse;
+ private final ComponentName mCallScreeningComponent;
+
+ /**
+ * Constructor for {@link CallFilteringCompletionInfo}
+ *
+ * @param isBlocked Whether any part of the call filtering process indicated that this call
+ * should be blocked.
+ * @param isInContacts Whether the caller is in the user's contacts.
+ * @param callResponse The instance of {@link CallScreeningService.CallResponse} provided
+ * by the {@link CallScreeningService} that processed this call, or
+ * {@code null} if no call screening service ran.
+ * @param callScreeningComponent The component of the {@link CallScreeningService}
+ * that processed this call, or {@link null} if no
+ * call screening service ran.
+ */
+ public CallFilteringCompletionInfo(boolean isBlocked, boolean isInContacts,
+ @Nullable CallScreeningService.CallResponse callResponse,
+ @Nullable ComponentName callScreeningComponent) {
+ mIsBlocked = isBlocked;
+ mIsInContacts = isInContacts;
+ mCallResponse = callResponse;
+ mCallScreeningComponent = callScreeningComponent;
+ }
+
+ /** @hide */
+ protected CallFilteringCompletionInfo(Parcel in) {
+ mIsBlocked = in.readByte() != 0;
+ mIsInContacts = in.readByte() != 0;
+ CallScreeningService.ParcelableCallResponse response
+ = in.readParcelable(CallScreeningService.class.getClassLoader());
+ mCallResponse = response == null ? null : response.toCallResponse();
+ mCallScreeningComponent = in.readParcelable(ComponentName.class.getClassLoader());
+ }
+
+ @NonNull
+ public static final Creator<CallFilteringCompletionInfo> CREATOR =
+ new Creator<CallFilteringCompletionInfo>() {
+ @Override
+ public CallFilteringCompletionInfo createFromParcel(Parcel in) {
+ return new CallFilteringCompletionInfo(in);
+ }
+
+ @Override
+ public CallFilteringCompletionInfo[] newArray(int size) {
+ return new CallFilteringCompletionInfo[size];
+ }
+ };
+
+ /**
+ * @return Whether any part of the call filtering process indicated that this call should be
+ * blocked.
+ */
+ public boolean isBlocked() {
+ return mIsBlocked;
+ }
+
+ /**
+ * @return Whether the caller is in the user's contacts.
+ */
+ public boolean isInContacts() {
+ return mIsInContacts;
+ }
+
+ /**
+ * @return The instance of {@link CallScreeningService.CallResponse} provided
+ * by the {@link CallScreeningService} that processed this
+ * call, or {@code null} if no call screening service ran.
+ */
+ public @Nullable CallScreeningService.CallResponse getCallResponse() {
+ return mCallResponse;
+ }
+
+ /**
+ * @return The component of the {@link CallScreeningService}
+ * that processed this call, or {@code null} if no call screening service ran.
+ */
+ public @Nullable ComponentName getCallScreeningComponent() {
+ return mCallScreeningComponent;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "CallFilteringCompletionInfo{" +
+ "mIsBlocked=" + mIsBlocked +
+ ", mIsInContacts=" + mIsInContacts +
+ ", mCallResponse=" + mCallResponse +
+ ", mCallScreeningPackageName='" + mCallScreeningComponent + '\'' +
+ '}';
+ }
+
+ /** @hide */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeByte((byte) (mIsBlocked ? 1 : 0));
+ dest.writeByte((byte) (mIsInContacts ? 1 : 0));
+ dest.writeParcelable(mCallResponse == null ? null : mCallResponse.toParcelable(), 0);
+ dest.writeParcelable(mCallScreeningComponent, 0);
+ }
+ }
+
+ /**
* Indicates that call filtering in Telecom is complete
*
* This method is called for a connection created via
@@ -3386,24 +3504,13 @@
* Telecom, including checking the blocked number db, per-contact settings, and custom call
* filtering apps.
*
- * @param isBlocked {@code true} if the call was blocked, {@code false} otherwise. If this is
- * {@code true}, {@link #onDisconnect()} will be called soon after
- * this is called.
- * @param isInContacts Indicates whether the caller is in the user's contacts list.
- * @param callScreeningResponse The response that was returned from the
- * {@link CallScreeningService} that handled this call. If no
- * response was received from a call screening service,
- * this will be {@code null}.
- * @param isResponseFromSystemDialer Whether {@code callScreeningResponse} was sent from the
- * system dialer. If {@code callScreeningResponse} is
- * {@code null}, this will be {@code false}.
+ * @param callFilteringCompletionInfo Info provided by Telecom on the results of call filtering.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_CONTACTS)
- public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts,
- @Nullable CallScreeningService.CallResponse callScreeningResponse,
- boolean isResponseFromSystemDialer) { }
+ public void onCallFilteringCompleted(
+ @NonNull CallFilteringCompletionInfo callFilteringCompletionInfo) { }
static String toLogSafePhoneNumber(String number) {
// For unknown number, log empty string.
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 966ece3..c189b19 100755
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -758,19 +758,15 @@
}
@Override
- public void onCallFilteringCompleted(String callId, boolean isBlocked, boolean isInContacts,
- CallScreeningService.ParcelableCallResponse callScreeningResponse,
- boolean isResponseFromSystemDialer,
+ public void onCallFilteringCompleted(String callId,
+ Connection.CallFilteringCompletionInfo completionInfo,
Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_CALL_FILTERING_COMPLETED);
try {
SomeArgs args = SomeArgs.obtain();
args.arg1 = callId;
- args.arg2 = isBlocked;
- args.arg3 = isInContacts;
- args.arg4 = callScreeningResponse;
- args.arg5 = isResponseFromSystemDialer;
- args.arg6 = Log.createSubsession();
+ args.arg2 = completionInfo;
+ args.arg3 = Log.createSubsession();
mHandler.obtainMessage(MSG_ON_CALL_FILTERING_COMPLETED, args).sendToTarget();
} finally {
Log.endSession();
@@ -1441,16 +1437,12 @@
case MSG_ON_CALL_FILTERING_COMPLETED: {
SomeArgs args = (SomeArgs) msg.obj;
try {
- Log.continueSession((Session) args.arg6,
+ Log.continueSession((Session) args.arg3,
SESSION_HANDLER + SESSION_CALL_FILTERING_COMPLETED);
String callId = (String) args.arg1;
- boolean isBlocked = (boolean) args.arg2;
- boolean isInContacts = (boolean) args.arg3;
- CallScreeningService.ParcelableCallResponse callScreeningResponse =
- (CallScreeningService.ParcelableCallResponse) args.arg4;
- boolean isResponseFromSystemDialer = (boolean) args.arg5;
- onCallFilteringCompleted(callId, isBlocked, isInContacts,
- callScreeningResponse, isResponseFromSystemDialer);
+ Connection.CallFilteringCompletionInfo completionInfo =
+ (Connection.CallFilteringCompletionInfo) args.arg2;
+ onCallFilteringCompleted(callId, completionInfo);
} finally {
args.recycle();
Log.endSession();
@@ -2466,16 +2458,12 @@
}
}
- private void onCallFilteringCompleted(String callId, boolean isBlocked, boolean isInContacts,
- CallScreeningService.ParcelableCallResponse callScreeningResponse,
- boolean isResponseFromSystemDialer) {
- Log.i(this, "onCallFilteringCompleted(%s, %b, %b, %s, %b)", callId,
- isBlocked, isInContacts, callScreeningResponse, isResponseFromSystemDialer);
+ private void onCallFilteringCompleted(String callId, Connection.CallFilteringCompletionInfo
+ callFilteringCompletionInfo) {
+ Log.i(this, "onCallFilteringCompleted(%s, %s)", callId, callFilteringCompletionInfo);
Connection connection = findConnectionForAction(callId, "onCallFilteringCompleted");
if (connection != null) {
- connection.onCallFilteringCompleted(isBlocked, isInContacts,
- callScreeningResponse == null ? null : callScreeningResponse.toCallResponse(),
- isResponseFromSystemDialer);
+ connection.onCallFilteringCompleted(callFilteringCompletionInfo);
}
}
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 6c6097a..7a6fddb 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -1202,27 +1202,18 @@
/**
* Notifies this {@link RemoteConnection} that call filtering has completed, as well as
* the results of a contacts lookup for the remote party.
- * @param isBlocked Whether call filtering indicates that the call should be blocked
- * @param isInContacts Whether the remote party is in the user's contacts
- * @param callScreeningResponse The response that was returned from the
- * {@link CallScreeningService} that handled this call. If no
- * response was received from a call screening service,
- * this will be {@code null}.
- * @param isResponseFromSystemDialer Whether {@code callScreeningResponse} was sent from the
- * system dialer. If {@code callScreeningResponse} is
- * {@code null}, this will be {@code false}.
+ *
+ * @param completionInfo Info provided by Telecom on the results of call filtering.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_CONTACTS)
- public void onCallFilteringCompleted(boolean isBlocked, boolean isInContacts,
- @Nullable CallScreeningService.CallResponse callScreeningResponse,
- boolean isResponseFromSystemDialer) {
+ public void onCallFilteringCompleted(
+ @NonNull Connection.CallFilteringCompletionInfo completionInfo) {
Log.startSession("RC.oCFC", getActiveOwnerInfo());
try {
if (mConnected) {
- mConnectionService.onCallFilteringCompleted(mConnectionId, isBlocked, isInContacts,
- callScreeningResponse.toParcelable(), isResponseFromSystemDialer,
+ mConnectionService.onCallFilteringCompleted(mConnectionId, completionInfo,
null /*Session.Info*/);
}
} catch (RemoteException ignored) {
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 7599e18..d72f8aa 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -20,7 +20,7 @@
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.telecom.CallAudioState;
-import android.telecom.CallScreeningService;
+import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.Logging.Session;
import android.telecom.PhoneAccountHandle;
@@ -119,9 +119,9 @@
void sendCallEvent(String callId, String event, in Bundle extras, in Session.Info sessionInfo);
- void onCallFilteringCompleted(String callId, boolean isBlocked, boolean isInContacts,
- in CallScreeningService.ParcelableCallResponse callScreeningResponse,
- boolean isResponseFromSystemDialer, in Session.Info sessionInfo);
+ void onCallFilteringCompleted(String callId,
+ in Connection.CallFilteringCompletionInfo completionInfo,
+ in Session.Info sessionInfo);
void onExtrasChanged(String callId, in Bundle extras, in Session.Info sessionInfo);
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index c6757fb..4ae11b8 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -111,6 +111,7 @@
public @interface NetworkType {
}
+ // TODO(b/180542000): remove and replace references with @ApnSetting.ApnType
@IntDef(flag = true, prefix = {"TYPE_"}, value = {
ApnSetting.TYPE_DEFAULT,
ApnSetting.TYPE_MMS,
@@ -124,6 +125,7 @@
ApnSetting.TYPE_EMERGENCY,
ApnSetting.TYPE_MCX,
ApnSetting.TYPE_XCAP,
+ // ApnSetting.TYPE_ENTERPRISE
})
@Retention(RetentionPolicy.SOURCE)
public @interface ApnType {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8c68d85..3d43d03 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5321,7 +5321,7 @@
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY,
new String[0]);
sDefaults.putStringArray(KEY_APN_PRIORITY_STRING_ARRAY, new String[] {
- "default:0", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2",
+ "default:0", "enterprise:1", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2",
"ims:2", "cbs:2", "ia:2", "emergency:2", "mcx:3", "xcap:3"
});
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 99a77ae5..c8ed82c 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -917,6 +917,10 @@
public static final int HANDOFF_PREFERENCE_CHANGED = 0x8CB;
/** Data call fail due to the slice not being allowed for the data call. */
public static final int SLICE_REJECTED = 0x8CC;
+ /** No matching rule available for the request, and match-all rule is not allowed for it. */
+ public static final int MATCH_ALL_RULE_NOT_ALLOWED = 0x8CD;
+ /** If connection failed for all matching URSP rules. */
+ public static final int ALL_MATCHING_RULES_FAILED = 0x8CE;
//IKE error notifications message as specified in 3GPP TS 24.302 (Section 8.1.2.2).
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 6c013df..4926687 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2649,6 +2649,37 @@
*/
public void sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
Bundle configOverrides, PendingIntent sentIntent) {
+ sendMultimediaMessage(context, contentUri, locationUrl, configOverrides, sentIntent,
+ 0L /* messageId */);
+ }
+
+ /**
+ * Send an MMS message
+ *
+ * Same as {@link #sendMultimediaMessage(Context context, Uri contentUri, String locationUrl,
+ * Bundle configOverrides, PendingIntent sentIntent)}, but adds an optional messageId.
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail sending the MMS message because no
+ * suitable default subscription could be found. In this case, if {@code sentIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the
+ * conditions where this operation may fail.
+ * </p>
+ *
+ * @param context application context
+ * @param contentUri the content Uri from which the message pdu will be read
+ * @param locationUrl the optional location url where message should be sent to
+ * @param configOverrides the carrier-specific messaging configuration values to override for
+ * sending the message.
+ * @param sentIntent if not NULL this <code>PendingIntent</code> is
+ * broadcast when the message is successfully sent, or failed
+ * @param messageId an id that uniquely identifies the message requested to be sent.
+ * Used for logging and diagnostics purposes. The id may be 0.
+ * @throws IllegalArgumentException if contentUri is empty
+ */
+ public void sendMultimediaMessage(@NonNull Context context, @NonNull Uri contentUri,
+ @Nullable String locationUrl, @Nullable Bundle configOverrides,
+ @Nullable PendingIntent sentIntent, long messageId) {
if (contentUri == null) {
throw new IllegalArgumentException("Uri contentUri null");
}
@@ -2658,7 +2689,7 @@
@Override
public void onSuccess(int subId) {
m.sendMultimediaMessage(subId, contentUri, locationUrl, configOverrides,
- sentIntent, 0L /* messageId */);
+ sentIntent, messageId);
}
@Override
@@ -2692,6 +2723,39 @@
*/
public void downloadMultimediaMessage(Context context, String locationUrl, Uri contentUri,
Bundle configOverrides, PendingIntent downloadedIntent) {
+ downloadMultimediaMessage(context, locationUrl, contentUri, configOverrides,
+ downloadedIntent, 0L /* messageId */);
+ }
+
+ /**
+ * Download an MMS message from carrier by a given location URL
+ *
+ * Same as {@link #downloadMultimediaMessage(Context context, String locationUrl,
+ * Uri contentUri, Bundle configOverrides, PendingIntent downloadedIntent)},
+ * but adds an optional messageId.
+ * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this
+ * manager on a multi-SIM device, this operation may fail downloading the MMS message because no
+ * suitable default subscription could be found. In this case, if {@code downloadedIntent} is
+ * non-null, then the {@link PendingIntent} will be sent with an error code
+ * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the
+ * conditions where this operation may fail.
+ * </p>
+ *
+ * @param context application context
+ * @param locationUrl the location URL of the MMS message to be downloaded, usually obtained
+ * from the MMS WAP push notification
+ * @param contentUri the content uri to which the downloaded pdu will be written
+ * @param configOverrides the carrier-specific messaging configuration values to override for
+ * downloading the message.
+ * @param downloadedIntent if not NULL this <code>PendingIntent</code> is
+ * broadcast when the message is downloaded, or the download is failed
+ * @param messageId an id that uniquely identifies the message requested to be downloaded.
+ * Used for logging and diagnostics purposes. The id may be 0.
+ * @throws IllegalArgumentException if locationUrl or contentUri is empty
+ */
+ public void downloadMultimediaMessage(@NonNull Context context, @NonNull String locationUrl,
+ @NonNull Uri contentUri, @Nullable Bundle configOverrides,
+ @Nullable PendingIntent downloadedIntent, long messageId) {
if (TextUtils.isEmpty(locationUrl)) {
throw new IllegalArgumentException("Empty MMS location URL");
}
@@ -2704,7 +2768,7 @@
@Override
public void onSuccess(int subId) {
m.downloadMultimediaMessage(subId, locationUrl, contentUri, configOverrides,
- downloadedIntent, 0L /* messageId */);
+ downloadedIntent, messageId);
}
@Override
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index d58fa912..b503733 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -28,8 +28,6 @@
import android.os.Parcelable;
import android.provider.Telephony;
import android.provider.Telephony.Carriers;
-import android.telephony.Annotation;
-import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.NetworkType;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
@@ -116,6 +114,31 @@
public static final int TYPE_MCX = ApnTypes.MCX;
/** APN type for XCAP. */
public static final int TYPE_XCAP = ApnTypes.XCAP;
+ /**
+ * APN type for ENTERPRISE.
+ * @hide
+ */
+ public static final int TYPE_ENTERPRISE = TYPE_XCAP << 1;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"TYPE_"}, value = {
+ TYPE_DEFAULT,
+ TYPE_MMS,
+ TYPE_SUPL,
+ TYPE_DUN,
+ TYPE_HIPRI,
+ TYPE_FOTA,
+ TYPE_IMS,
+ TYPE_CBS,
+ TYPE_IA,
+ TYPE_EMERGENCY,
+ TYPE_MCX,
+ TYPE_XCAP,
+ TYPE_ENTERPRISE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ApnType {
+ }
// Possible values for authentication types.
/** No authentication type. */
@@ -151,6 +174,7 @@
TYPE_MMS_STRING,
TYPE_SUPL_STRING,
TYPE_XCAP_STRING,
+ TYPE_ENTERPRISE_STRING,
}, prefix = "TYPE_", suffix = "_STRING")
@Retention(RetentionPolicy.SOURCE)
public @interface ApnTypeString {}
@@ -291,6 +315,12 @@
@SystemApi
public static final String TYPE_XCAP_STRING = "xcap";
+ /**
+ * APN type for ENTERPRISE traffic.
+ * @hide
+ */
+ public static final String TYPE_ENTERPRISE_STRING = "enterprise";
+
/** @hide */
@IntDef(prefix = { "AUTH_TYPE_" }, value = {
@@ -370,6 +400,7 @@
APN_TYPE_STRING_MAP.put(TYPE_EMERGENCY_STRING, TYPE_EMERGENCY);
APN_TYPE_STRING_MAP.put(TYPE_MCX_STRING, TYPE_MCX);
APN_TYPE_STRING_MAP.put(TYPE_XCAP_STRING, TYPE_XCAP);
+ APN_TYPE_STRING_MAP.put(TYPE_ENTERPRISE_STRING, TYPE_ENTERPRISE);
APN_TYPE_INT_MAP = new ArrayMap<>();
APN_TYPE_INT_MAP.put(TYPE_DEFAULT, TYPE_DEFAULT_STRING);
@@ -384,6 +415,7 @@
APN_TYPE_INT_MAP.put(TYPE_EMERGENCY, TYPE_EMERGENCY_STRING);
APN_TYPE_INT_MAP.put(TYPE_MCX, TYPE_MCX_STRING);
APN_TYPE_INT_MAP.put(TYPE_XCAP, TYPE_XCAP_STRING);
+ APN_TYPE_INT_MAP.put(TYPE_ENTERPRISE, TYPE_ENTERPRISE_STRING);
PROTOCOL_STRING_MAP = new ArrayMap<>();
PROTOCOL_STRING_MAP.put("IP", PROTOCOL_IP);
@@ -1490,7 +1522,7 @@
* @hide
*/
@SystemApi
- public static @NonNull @ApnTypeString String getApnTypeString(@Annotation.ApnType int apnType) {
+ public static @NonNull @ApnTypeString String getApnTypeString(@ApnType int apnType) {
if (apnType == TYPE_ALL) {
return "*";
}
@@ -1503,7 +1535,7 @@
* when provided with an invalid int for compatibility purposes.
* @hide
*/
- public static @NonNull String getApnTypeStringInternal(@Annotation.ApnType int apnType) {
+ public static @NonNull String getApnTypeStringInternal(@ApnType int apnType) {
String result = getApnTypeString(apnType);
return TextUtils.isEmpty(result) ? "Unknown" : result;
}
@@ -1517,7 +1549,7 @@
* @hide
*/
@SystemApi
- public static @Annotation.ApnType int getApnTypeInt(@NonNull @ApnTypeString String apnType) {
+ public static @ApnType int getApnTypeInt(@NonNull @ApnTypeString String apnType) {
return APN_TYPE_STRING_MAP.getOrDefault(apnType.toLowerCase(), 0);
}
@@ -2162,7 +2194,7 @@
public ApnSetting build() {
if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI
| TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
- | TYPE_XCAP)) == 0
+ | TYPE_XCAP | TYPE_ENTERPRISE)) == 0
|| TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
return null;
}
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index bd4bf07..a764229 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -138,6 +138,7 @@
private final Qos mDefaultQos;
private final List<QosBearerSession> mQosBearerSessions;
private final SliceInfo mSliceInfo;
+ private final List<TrafficDescriptor> mTrafficDescriptors;
/**
* @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error.
@@ -189,6 +190,7 @@
mDefaultQos = null;
mQosBearerSessions = new ArrayList<>();
mSliceInfo = null;
+ mTrafficDescriptors = new ArrayList<>();
}
private DataCallResponse(@DataFailureCause int cause, long suggestedRetryTime, int id,
@@ -198,7 +200,7 @@
@Nullable List<InetAddress> pcscfAddresses, int mtu, int mtuV4, int mtuV6,
@HandoverFailureMode int handoverFailureMode, int pduSessionId,
@Nullable Qos defaultQos, @Nullable List<QosBearerSession> qosBearerSessions,
- @Nullable SliceInfo sliceInfo) {
+ @Nullable SliceInfo sliceInfo, @Nullable List<TrafficDescriptor> trafficDescriptors) {
mCause = cause;
mSuggestedRetryTime = suggestedRetryTime;
mId = id;
@@ -219,8 +221,11 @@
mHandoverFailureMode = handoverFailureMode;
mPduSessionId = pduSessionId;
mDefaultQos = defaultQos;
- mQosBearerSessions = qosBearerSessions;
+ mQosBearerSessions = (qosBearerSessions == null)
+ ? new ArrayList<>() : new ArrayList<>(qosBearerSessions);
mSliceInfo = sliceInfo;
+ mTrafficDescriptors = (trafficDescriptors == null)
+ ? new ArrayList<>() : new ArrayList<>(trafficDescriptors);
}
/** @hide */
@@ -249,6 +254,8 @@
mQosBearerSessions = new ArrayList<>();
source.readList(mQosBearerSessions, QosBearerSession.class.getClassLoader());
mSliceInfo = source.readParcelable(SliceInfo.class.getClassLoader());
+ mTrafficDescriptors = new ArrayList<>();
+ source.readList(mTrafficDescriptors, TrafficDescriptor.class.getClassLoader());
}
/**
@@ -381,7 +388,6 @@
*
* @hide
*/
-
@Nullable
public Qos getDefaultQos() {
return mDefaultQos;
@@ -406,6 +412,14 @@
return mSliceInfo;
}
+ /**
+ * @return The traffic descriptors related to this data connection.
+ */
+ @NonNull
+ public List<TrafficDescriptor> getTrafficDescriptors() {
+ return mTrafficDescriptors;
+ }
+
@NonNull
@Override
public String toString() {
@@ -429,6 +443,7 @@
.append(" defaultQos=").append(mDefaultQos)
.append(" qosBearerSessions=").append(mQosBearerSessions)
.append(" sliceInfo=").append(mSliceInfo)
+ .append(" trafficDescriptors=").append(mTrafficDescriptors)
.append("}");
return sb.toString();
}
@@ -443,15 +458,22 @@
DataCallResponse other = (DataCallResponse) o;
- final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null) ?
- mDefaultQos == other.mDefaultQos :
- mDefaultQos.equals(other.mDefaultQos);
+ final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null)
+ ? mDefaultQos == other.mDefaultQos
+ : mDefaultQos.equals(other.mDefaultQos);
- final boolean isQosBearerSessionsSame = (mQosBearerSessions == null || mQosBearerSessions == null) ?
- mQosBearerSessions == other.mQosBearerSessions :
- mQosBearerSessions.size() == other.mQosBearerSessions.size()
+ final boolean isQosBearerSessionsSame =
+ (mQosBearerSessions == null || other.mQosBearerSessions == null)
+ ? mQosBearerSessions == other.mQosBearerSessions
+ : mQosBearerSessions.size() == other.mQosBearerSessions.size()
&& mQosBearerSessions.containsAll(other.mQosBearerSessions);
+ final boolean isTrafficDescriptorsSame =
+ (mTrafficDescriptors == null || other.mTrafficDescriptors == null)
+ ? mTrafficDescriptors == other.mTrafficDescriptors
+ : mTrafficDescriptors.size() == other.mTrafficDescriptors.size()
+ && mTrafficDescriptors.containsAll(other.mTrafficDescriptors);
+
return mCause == other.mCause
&& mSuggestedRetryTime == other.mSuggestedRetryTime
&& mId == other.mId
@@ -473,7 +495,8 @@
&& mPduSessionId == other.mPduSessionId
&& isQosSame
&& isQosBearerSessionsSame
- && Objects.equals(mSliceInfo, other.mSliceInfo);
+ && Objects.equals(mSliceInfo, other.mSliceInfo)
+ && isTrafficDescriptorsSame;
}
@Override
@@ -481,7 +504,7 @@
return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType,
mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses,
mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId, mDefaultQos,
- mQosBearerSessions, mSliceInfo);
+ mQosBearerSessions, mSliceInfo, mTrafficDescriptors);
}
@Override
@@ -517,6 +540,7 @@
}
dest.writeList(mQosBearerSessions);
dest.writeParcelable(mSliceInfo, flags);
+ dest.writeList(mTrafficDescriptors);
}
public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR =
@@ -602,6 +626,8 @@
private SliceInfo mSliceInfo;
+ private List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>();
+
/**
* Default constructor for Builder.
*/
@@ -841,6 +867,24 @@
}
/**
+ * The traffic descriptors for this data connection, as defined in 3GPP TS 24.526
+ * Section 5.2. They are used for URSP traffic matching as described in 3GPP TS 24.526
+ * Section 4.2.2. They includes an optional DNN, which, if present, must be used for traffic
+ * matching; it does not specify the end point to be used for the data call. The end point
+ * is specified by {@link DataProfile}, which must be used as the end point if one is not
+ * specified through URSP rules.
+ *
+ * @param trafficDescriptors the traffic descriptors for the data call.
+ *
+ * @return The same instance of the builder.
+ */
+ public @NonNull Builder setTrafficDescriptors(
+ @NonNull List<TrafficDescriptor> trafficDescriptors) {
+ mTrafficDescriptors = trafficDescriptors;
+ return this;
+ }
+
+ /**
* Build the DataCallResponse.
*
* @return the DataCallResponse object.
@@ -849,7 +893,7 @@
return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus,
mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses,
mPcscfAddresses, mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId,
- mDefaultQos, mQosBearerSessions, mSliceInfo);
+ mDefaultQos, mQosBearerSessions, mSliceInfo, mTrafficDescriptors);
}
}
}
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 484c318..f5f29c6 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -200,6 +200,17 @@
* handover is occurring from EPDG to 5G. If the slice passed is rejected, then
* {@link DataCallResponse#getCause()} is
* {@link android.telephony.DataFailCause#SLICE_REJECTED}.
+ * @param trafficDescriptor {@link TrafficDescriptor} for which data connection needs to be
+ * established. It is used for URSP traffic matching as described in 3GPP TS 24.526
+ * Section 4.2.2. It includes an optional DNN which, if present, must be used for
+ * traffic matching; it does not specify the end point to be used for the data call.
+ * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this
+ * request is allowed. If false, this request must not use the match-all URSP rule
+ * and if a non-match-all rule is not found (or if URSP rules are not available) then
+ * {@link DataCallResponse#getCause()} is
+ * {@link android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed
+ * as some requests need to have a hard failure if the intention cannot be met,
+ * for example, a zero-rating slice.
* @param callback The result callback for this request.
*/
public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile,
@@ -207,6 +218,7 @@
@SetupDataReason int reason,
@Nullable LinkProperties linkProperties,
@IntRange(from = 0, to = 15) int pduSessionId, @Nullable SliceInfo sliceInfo,
+ @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
@NonNull DataServiceCallback callback) {
/* Call the old version since the new version isn't supported */
setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming, reason,
@@ -403,10 +415,13 @@
public final LinkProperties linkProperties;
public final int pduSessionId;
public final SliceInfo sliceInfo;
+ public final TrafficDescriptor trafficDescriptor;
+ public final boolean matchAllRuleAllowed;
public final IDataServiceCallback callback;
SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, int reason, LinkProperties linkProperties,
- int pduSessionId, SliceInfo sliceInfo, IDataServiceCallback callback) {
+ boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId,
+ SliceInfo sliceInfo, TrafficDescriptor trafficDescriptor,
+ boolean matchAllRuleAllowed, IDataServiceCallback callback) {
this.accessNetworkType = accessNetworkType;
this.dataProfile = dataProfile;
this.isRoaming = isRoaming;
@@ -415,6 +430,8 @@
this.reason = reason;
this.pduSessionId = pduSessionId;
this.sliceInfo = sliceInfo;
+ this.trafficDescriptor = trafficDescriptor;
+ this.matchAllRuleAllowed = matchAllRuleAllowed;
this.callback = callback;
}
}
@@ -525,7 +542,8 @@
setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
setupDataCallRequest.linkProperties, setupDataCallRequest.pduSessionId,
- setupDataCallRequest.sliceInfo,
+ setupDataCallRequest.sliceInfo, setupDataCallRequest.trafficDescriptor,
+ setupDataCallRequest.matchAllRuleAllowed,
(setupDataCallRequest.callback != null)
? new DataServiceCallback(setupDataCallRequest.callback)
: null);
@@ -690,11 +708,12 @@
public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming, int reason,
LinkProperties linkProperties, int pduSessionId, SliceInfo sliceInfo,
+ TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
IDataServiceCallback callback) {
mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0,
new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
- callback))
+ trafficDescriptor, matchAllRuleAllowed, callback))
.sendToTarget();
}
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index e0b9a1a..81f5fd3 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -20,6 +20,7 @@
import android.telephony.data.DataProfile;
import android.telephony.data.IDataServiceCallback;
import android.telephony.data.SliceInfo;
+import android.telephony.data.TrafficDescriptor;
/**
* {@hide}
@@ -30,7 +31,9 @@
void removeDataServiceProvider(int slotId);
void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
boolean allowRoaming, int reason, in LinkProperties linkProperties,
- int pduSessionId, in SliceInfo sliceInfo, IDataServiceCallback callback);
+ int pduSessionId, in SliceInfo sliceInfo,
+ in TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed,
+ IDataServiceCallback callback);
void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
void setInitialAttachApn(int slotId, in DataProfile dataProfile, boolean isRoaming,
IDataServiceCallback callback);
diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.aidl b/telephony/java/android/telephony/data/TrafficDescriptor.aidl
new file mode 100644
index 0000000..a9c7604
--- /dev/null
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/** @hide */
+package android.telephony.data;
+
+parcelable TrafficDescriptor;
diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java
new file mode 100644
index 0000000..480379d
--- /dev/null
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.java
@@ -0,0 +1,111 @@
+/*
+ * 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.telephony.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for URSP traffic
+ * matching as described in 3GPP TS 24.526 Section 4.2.2. It includes an optional DNN, which,
+ * if present, must be used for traffic matching; it does not specify the end point to be used for
+ * the data call.
+ * @hide
+ */
+@SystemApi
+public final class TrafficDescriptor implements Parcelable {
+ private final String mDnn;
+ private final String mOsAppId;
+
+ private TrafficDescriptor(@NonNull Parcel in) {
+ mDnn = in.readString();
+ mOsAppId = in.readString();
+ }
+
+ /**
+ * Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2
+ * @param dnn optional DNN, which must be used for traffic matching, if present
+ * @param osAppId OsId + osAppId of the traffic descriptor
+ */
+ public TrafficDescriptor(@Nullable String dnn, @Nullable String osAppId) {
+ mDnn = dnn;
+ mOsAppId = osAppId;
+ }
+
+ /**
+ * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003.
+ * @return the DNN of this traffic descriptor.
+ */
+ public @Nullable String getDnn() {
+ return mDnn;
+ }
+
+ /**
+ * OsAppId represents the OsId + OsAppId as defined in 3GPP TS 24.526 Section 5.2.
+ * @return the OS App ID of this traffic descriptor.
+ */
+ public @Nullable String getOsAppId() {
+ return mOsAppId;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull @Override
+ public String toString() {
+ return "TrafficDescriptor={mDnn=" + mDnn + ", mOsAppId=" + mOsAppId + "}";
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mDnn);
+ dest.writeString(mOsAppId);
+ }
+
+ public static final @NonNull Parcelable.Creator<TrafficDescriptor> CREATOR =
+ new Parcelable.Creator<TrafficDescriptor>() {
+ @Override
+ public @NonNull TrafficDescriptor createFromParcel(@NonNull Parcel source) {
+ return new TrafficDescriptor(source);
+ }
+
+ @Override
+ public @NonNull TrafficDescriptor[] newArray(int size) {
+ return new TrafficDescriptor[size];
+ }
+ };
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ TrafficDescriptor that = (TrafficDescriptor) o;
+ return Objects.equals(mDnn, that.mDnn) && Objects.equals(mOsAppId, that.mOsAppId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDnn, mOsAppId);
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5c25524..0048d53 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2055,6 +2055,11 @@
int setImsProvisioningString(int subId, int key, String value);
/**
+ * Start emergency callback mode for testing.
+ */
+ void startEmergencyCallbackMode();
+
+ /**
* Update Emergency Number List for Test Mode.
*/
void updateEmergencyNumberListTestMode(int action, in EmergencyNumber num);
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 151187c..3a99f0e0 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -126,6 +126,7 @@
* connections.<br/>
* APN_TYPE_ALL is a special type to indicate that this APN entry can
* service all data connections.
+ * TODO: remove these and use the reference to ApnSetting.TYPE_XXX_STRING instead
*/
public static final String APN_TYPE_ALL = ApnSetting.TYPE_ALL_STRING;
/** APN type for default data traffic */
@@ -153,20 +154,8 @@
public static final String APN_TYPE_MCX = ApnSetting.TYPE_MCX_STRING;
/** APN type for XCAP */
public static final String APN_TYPE_XCAP = ApnSetting.TYPE_XCAP_STRING;
- /** Array of all APN types */
- public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
- APN_TYPE_MMS,
- APN_TYPE_SUPL,
- APN_TYPE_DUN,
- APN_TYPE_HIPRI,
- APN_TYPE_FOTA,
- APN_TYPE_IMS,
- APN_TYPE_CBS,
- APN_TYPE_IA,
- APN_TYPE_EMERGENCY,
- APN_TYPE_MCX,
- APN_TYPE_XCAP,
- };
+ // /** APN type for enterprise */
+ // public static final String APN_TYPE_ENTERPRISE = ApnSetting.TYPE_ENTERPRISE_STRING;
public static final int RIL_CARD_MAX_APPS = 8;
diff --git a/test-base/Android.bp b/test-base/Android.bp
index 0b7a398..9bd639b 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -49,6 +49,12 @@
compile_dex: true,
default_to_stubs: true,
+
+ // Additional hiddenapi annotations are provided in a separate module.
+ // TODO(b/180295980) - investigate whether this can be removed
+ hiddenapi_additional_annotations: [
+ "android.test.base-hiddenapi-annotations",
+ ],
}
// Build the android.test.base_static library
@@ -91,8 +97,9 @@
// ===============================================
// This contains the android.test classes from android.test.base plus
// the com.android.internal.util.Predicate[s] classes. This is only
-// intended for inclusion in android.test.legacy and must not be used
-// elsewhere.
+// intended for inclusion in android.test.legacy and in
+// android.test.base-hiddenapi-annotations to avoid a dependency cycle and must
+// not be used elsewhere.
java_library_static {
name: "android.test.base-minus-junit",
diff --git a/test-base/hiddenapi/Android.bp b/test-base/hiddenapi/Android.bp
index d4f52d0..1466590 100644
--- a/test-base/hiddenapi/Android.bp
+++ b/test-base/hiddenapi/Android.bp
@@ -14,11 +14,6 @@
// limitations under the License.
//
-// Provided solely to contribute information about which hidden parts of the android.test.base
-// library are used by apps. The source files are stubs of the actual files in ../src which use the
-// UnsupportedAppUsage annotation to tag those methods that are accessible via the hiddenapi.
-// Relies on the convention that modules with name <x>-hiddenapi provide hiddenapi information for
-// module <x> that is on the bootclasspath.
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
@@ -28,14 +23,20 @@
default_applicable_licenses: ["frameworks_base_license"],
}
+// Provided solely to contribute information about which hidden parts of the android.test.base
+// library are used by apps. The source files are stubs of the actual files in ../src which use the
+// UnsupportedAppUsage annotation to tag those methods that are accessible via the hiddenapi.
java_library {
- name: "android.test.base-hiddenapi",
+ name: "android.test.base-hiddenapi-annotations",
compile_dex: true,
srcs: ["src/**/*.java"],
libs: [
- "android.test.base",
+ // Use this instead of `android.test.base` to avoid a dependency cycle
+ // as `android.test.base` depends on this.
+ "android.test.base-minus-junit",
+ "junit",
"unsupportedappusage",
],
}
diff --git a/tests/BatteryStatsPerfTest/Android.bp b/tests/BatteryStatsPerfTest/Android.bp
index 58ccec7..5233a5b 100644
--- a/tests/BatteryStatsPerfTest/Android.bp
+++ b/tests/BatteryStatsPerfTest/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "BatteryStatsPerfTests",
srcs: ["src/**/*.java"],
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index 7d29cdd..a8b7b05 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -21,8 +21,6 @@
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.NAV_BAR_LAYER_NAME
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper.Companion.STATUS_BAR_WINDOW_NAME
-const val APP_PAIR_SPLIT_DIVIDER = "AppPairSplitDivider"
-const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
const val WALLPAPER_TITLE = "Wallpaper"
fun FlickerTestParameter.statusBarWindowIsAlwaysVisible() {
@@ -64,9 +62,9 @@
fun FlickerTestParameter.wallpaperWindowBecomesInvisible() {
assertWm {
- this.showsBelowAppWindow("Wallpaper")
+ this.showsBelowAppWindow(WALLPAPER_TITLE)
.then()
- .hidesBelowAppWindow("Wallpaper")
+ .hidesBelowAppWindow(WALLPAPER_TITLE)
}
}
@@ -103,19 +101,19 @@
if (allStates) {
assertLayers {
if (startingBounds == endingBounds) {
- this.coversAtLeastRegion(startingBounds)
+ this.coversAtLeast(startingBounds)
} else {
- this.coversAtLeastRegion(startingBounds)
+ this.coversAtLeast(startingBounds)
.then()
- .coversAtLeastRegion(endingBounds)
+ .coversAtLeast(endingBounds)
}
}
} else {
assertLayersStart {
- this.coversAtLeastRegion(startingBounds)
+ this.coversAtLeast(startingBounds)
}
assertLayersEnd {
- this.coversAtLeastRegion(endingBounds)
+ this.coversAtLeast(endingBounds)
}
}
}
@@ -124,15 +122,15 @@
fun FlickerTestParameter.navBarLayerIsAlwaysVisible(rotatesScreen: Boolean = false) {
if (rotatesScreen) {
assertLayers {
- this.showsLayer(NAV_BAR_LAYER_NAME)
+ this.isVisible(NAV_BAR_LAYER_NAME)
.then()
- .hidesLayer(NAV_BAR_LAYER_NAME)
+ .isInvisible(NAV_BAR_LAYER_NAME)
.then()
- .showsLayer(NAV_BAR_LAYER_NAME)
+ .isVisible(NAV_BAR_LAYER_NAME)
}
} else {
assertLayers {
- this.showsLayer(NAV_BAR_LAYER_NAME)
+ this.isVisible(NAV_BAR_LAYER_NAME)
}
}
}
@@ -141,15 +139,15 @@
fun FlickerTestParameter.statusBarLayerIsAlwaysVisible(rotatesScreen: Boolean = false) {
if (rotatesScreen) {
assertLayers {
- this.showsLayer(STATUS_BAR_WINDOW_NAME)
+ this.isVisible(STATUS_BAR_WINDOW_NAME)
.then()
- hidesLayer(STATUS_BAR_WINDOW_NAME)
+ .isInvisible(STATUS_BAR_WINDOW_NAME)
.then()
- .showsLayer(STATUS_BAR_WINDOW_NAME)
+ .isVisible(STATUS_BAR_WINDOW_NAME)
}
} else {
assertLayers {
- this.showsLayer(STATUS_BAR_WINDOW_NAME)
+ this.isVisible(STATUS_BAR_WINDOW_NAME)
}
}
}
@@ -163,10 +161,10 @@
val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
assertLayersStart {
- this.hasVisibleRegion(NAV_BAR_LAYER_NAME, startingPos)
+ this.coversExactly(startingPos, NAV_BAR_LAYER_NAME)
}
assertLayersEnd {
- this.hasVisibleRegion(NAV_BAR_LAYER_NAME, endingPos)
+ this.coversExactly(endingPos, NAV_BAR_LAYER_NAME)
}
}
@@ -179,10 +177,10 @@
val endingPos = WindowUtils.getStatusBarPosition(endRotation)
assertLayersStart {
- this.hasVisibleRegion(STATUS_BAR_WINDOW_NAME, startingPos)
+ this.coversExactly(startingPos, STATUS_BAR_WINDOW_NAME)
}
assertLayersEnd {
- this.hasVisibleRegion(STATUS_BAR_WINDOW_NAME, endingPos)
+ this.coversExactly(endingPos, STATUS_BAR_WINDOW_NAME)
}
}
@@ -197,39 +195,41 @@
fun FlickerTestParameter.appLayerReplacesWallpaperLayer(appName: String) {
assertLayers {
- this.showsLayer("Wallpaper")
+ this.isVisible(WALLPAPER_TITLE)
.then()
- .replaceVisibleLayer("Wallpaper", appName)
+ .isInvisible(WALLPAPER_TITLE)
+ .isVisible(appName)
}
}
fun FlickerTestParameter.wallpaperLayerReplacesAppLayer(testApp: IAppHelper) {
assertLayers {
- this.showsLayer(testApp.getPackage())
+ this.isVisible(testApp.getPackage())
.then()
- .replaceVisibleLayer(testApp.getPackage(), WALLPAPER_TITLE)
+ .isInvisible(testApp.getPackage())
+ .isVisible(WALLPAPER_TITLE)
}
}
fun FlickerTestParameter.layerAlwaysVisible(packageName: String) {
assertLayers {
- this.showsLayer(packageName)
+ this.isVisible(packageName)
}
}
fun FlickerTestParameter.layerBecomesVisible(packageName: String) {
assertLayers {
- this.hidesLayer(packageName)
+ this.isInvisible(packageName)
.then()
- .showsLayer(packageName)
+ .isVisible(packageName)
}
}
fun FlickerTestParameter.layerBecomesInvisible(packageName: String) {
assertLayers {
- this.showsLayer(packageName)
+ this.isVisible(packageName)
.then()
- .hidesLayer(packageName)
+ .isInvisible(packageName)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index 212644c..3dfa31d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -23,23 +23,23 @@
fun FlickerTestParameter.imeLayerBecomesVisible() {
assertLayers {
- this.hidesLayer(IME_WINDOW_TITLE)
+ this.isInvisible(IME_WINDOW_TITLE)
.then()
- .showsLayer(IME_WINDOW_TITLE)
+ .isVisible(IME_WINDOW_TITLE)
}
}
fun FlickerTestParameter.imeLayerBecomesInvisible() {
assertLayers {
- this.showsLayer(IME_WINDOW_TITLE)
+ this.isVisible(IME_WINDOW_TITLE)
.then()
- .hidesLayer(IME_WINDOW_TITLE)
+ .isInvisible(IME_WINDOW_TITLE)
}
}
fun FlickerTestParameter.imeAppLayerIsAlwaysVisible(testApp: IAppHelper) {
assertLayers {
- this.showsLayer(testApp.getPackage())
+ this.isVisible(testApp.getPackage())
}
}
@@ -83,9 +83,8 @@
fun FlickerTestParameter.imeAppLayerBecomesInvisible(testApp: IAppHelper) {
assertLayers {
- this.skipUntilFirstAssertion()
- .showsLayer(testApp.getPackage())
+ this.isVisible(testApp.getPackage())
.then()
- .hidesLayer(testApp.getPackage())
+ .isInvisible(testApp.getPackage())
}
}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 3cc509f..20e4b88 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -16,13 +16,13 @@
package com.android.server.wm.flicker.rotation
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.focusDoesNotChange
import com.android.server.wm.flicker.helpers.SimpleAppHelper
@@ -54,7 +54,15 @@
testSpec: FlickerTestParameter
) : RotationTransition(testSpec) {
override val testApp = SimpleAppHelper(instrumentation)
- override fun getAppLaunchParams(configuration: Bundle): Map<String, String> = emptyMap()
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+ get() = {
+ super.transition(this, it)
+ setup {
+ test {
+ testApp.launchViaIntent(wmHelper)
+ }
+ }
+ }
@Presubmit
@Test
@@ -78,11 +86,11 @@
@Test
fun screenshotLayerBecomesInvisible() {
testSpec.assertLayers {
- this.showsLayer(testApp.getPackage())
+ this.isVisible(testApp.getPackage())
.then()
- .showsLayer(SCREENSHOT_LAYER)
+ .isVisible(SCREENSHOT_LAYER)
.then()
- .showsLayer(testApp.getPackage())
+ .isVisible(testApp.getPackage())
}
}
@@ -113,7 +121,7 @@
@Test
fun appLayerRotates_StartingPos() {
testSpec.assertLayersStart {
- this.hasVisibleRegion(testApp.getPackage(), startingPos)
+ this.coversExactly(startingPos, testApp.getPackage())
}
}
@@ -121,7 +129,7 @@
@Test
fun appLayerRotates_EndingPos() {
testSpec.assertLayersEnd {
- this.hasVisibleRegion(testApp.getPackage(), endingPos)
+ this.coversExactly(endingPos, testApp.getPackage())
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index 04ab84d..c391112 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -17,7 +17,6 @@
package com.android.server.wm.flicker.rotation
import android.app.Instrumentation
-import android.os.Bundle
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.FlickerBuilderProvider
import com.android.server.wm.flicker.FlickerTestParameter
@@ -31,36 +30,37 @@
import com.android.server.wm.flicker.startRotation
abstract class RotationTransition(protected val testSpec: FlickerTestParameter) {
+ protected abstract val testApp: StandardAppHelper
+
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
protected val startingPos get() = WindowUtils.getDisplayBounds(testSpec.config.startRotation)
protected val endingPos get() = WindowUtils.getDisplayBounds(testSpec.config.endRotation)
- protected abstract val testApp: StandardAppHelper
- protected abstract fun getAppLaunchParams(configuration: Bundle): Map<String, String>
+ protected open val transition: FlickerBuilder.(Map<String, Any?>) -> Unit = {
+ withTestName { testSpec.name }
+ repeat { testSpec.config.repetitions }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ eachRun {
+ this.setRotation(testSpec.config.startRotation)
+ }
+ }
+ teardown {
+ test {
+ testApp.exit()
+ }
+ }
+ transitions {
+ this.setRotation(testSpec.config.endRotation)
+ }
+ }
@FlickerBuilderProvider
fun buildFlicker(): FlickerBuilder {
return FlickerBuilder(instrumentation).apply {
- withTestName { testSpec.name }
- repeat { testSpec.config.repetitions }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- val extras = getAppLaunchParams(testSpec.config)
- testApp.launchViaIntent(wmHelper, stringExtras = extras)
- }
- eachRun {
- this.setRotation(testSpec.config.startRotation)
- }
- }
- teardown {
- test {
- testApp.exit()
- }
- }
- transitions {
- this.setRotation(testSpec.config.endRotation)
- }
+ transition(testSpec.config)
}
}
}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index ef1aead..fc5bcc7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.rotation
-import android.os.Bundle
import android.platform.test.annotations.Presubmit
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
@@ -24,6 +23,7 @@
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.appWindowAlwaysVisibleOnTop
+import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.focusDoesNotChange
import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper
@@ -58,9 +58,18 @@
) : RotationTransition(testSpec) {
override val testApp = SeamlessRotationAppHelper(instrumentation)
- override fun getAppLaunchParams(configuration: Bundle): Map<String, String> = mapOf(
- ActivityOptions.EXTRA_STARVE_UI_THREAD to configuration.starveUiThread.toString()
- )
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+ get() = {
+ super.transition(this, it)
+ setup {
+ test {
+ testApp.launchViaIntent(wmHelper,
+ stringExtras = mapOf(
+ ActivityOptions.EXTRA_STARVE_UI_THREAD to it.starveUiThread.toString())
+ )
+ }
+ }
+ }
@Presubmit
@Test
@@ -115,7 +124,7 @@
@Test
fun appLayerRotates() {
testSpec.assertLayers {
- this.hasVisibleRegion(testApp.`package`, startingPos)
+ this.coversExactly(startingPos, testApp.`package`)
}
}
@@ -126,12 +135,14 @@
companion object {
private val testFactory = FlickerTestParameterFactory.getInstance()
- private val Bundle.starveUiThread
- get() = this.getBoolean(ActivityOptions.EXTRA_STARVE_UI_THREAD, false)
+ private val Map<String, Any?>.starveUiThread
+ get() = this.getOrDefault(ActivityOptions.EXTRA_STARVE_UI_THREAD, false) as Boolean
- private fun FlickerTestParameter.createConfig(starveUiThread: Boolean): Bundle {
- val config = this.config.deepCopy()
- config.putBoolean(ActivityOptions.EXTRA_STARVE_UI_THREAD, starveUiThread)
+ private fun FlickerTestParameter.createConfig(
+ starveUiThread: Boolean
+ ): MutableMap<String, Any?> {
+ val config = this.config.toMutableMap()
+ config[ActivityOptions.EXTRA_STARVE_UI_THREAD] = starveUiThread
return config
}
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index a72b07c..335c8d0 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "InputTests",
srcs: ["src/**/*.kt"],
diff --git a/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt b/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt
index f919a3e..c19e5cc 100644
--- a/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt
+++ b/tests/Input/src/com/android/test/input/ViewFrameInfoTest.kt
@@ -62,15 +62,12 @@
fun testUpdateFrameInfoFromViewFrameInfo() {
val frameInfo = FrameInfo()
// By default, all values should be zero
- assertThat(frameInfo.frameInfo[FrameInfo.OLDEST_INPUT_EVENT]).isEqualTo(0)
- assertThat(frameInfo.frameInfo[FrameInfo.NEWEST_INPUT_EVENT]).isEqualTo(0)
+ // TODO(b/169866723): Use InputEventAssigner and assert INPUT_EVENT_ID
assertThat(frameInfo.frameInfo[FrameInfo.FLAGS]).isEqualTo(0)
assertThat(frameInfo.frameInfo[FrameInfo.DRAW_START]).isEqualTo(0)
// The values inside FrameInfo should match those from ViewFrameInfo after we update them
mViewFrameInfo.populateFrameInfo(frameInfo)
- assertThat(frameInfo.frameInfo[FrameInfo.OLDEST_INPUT_EVENT]).isEqualTo(10)
- assertThat(frameInfo.frameInfo[FrameInfo.NEWEST_INPUT_EVENT]).isEqualTo(20)
assertThat(frameInfo.frameInfo[FrameInfo.FLAGS]).isEqualTo(
FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED)
assertThat(frameInfo.frameInfo[FrameInfo.DRAW_START]).isGreaterThan(mTimeStarted)
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 95044dc..6e1cef4 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -105,6 +105,7 @@
key: "com.android.apex.apkrollback.test.key",
apps: ["TestAppAv1"],
installable: false,
+ updatable: false,
}
apex {
@@ -115,6 +116,7 @@
key: "com.android.apex.apkrollback.test.key",
apps: ["TestAppAv2"],
installable: false,
+ updatable: false,
}
apex {
@@ -125,4 +127,5 @@
key: "com.android.apex.apkrollback.test.key",
apps: ["TestAppACrashingV2"],
installable: false,
+ updatable: false,
}
diff --git a/tests/SilkFX/Android.bp b/tests/SilkFX/Android.bp
index 92e3efa..088d9a2 100644
--- a/tests/SilkFX/Android.bp
+++ b/tests/SilkFX/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "SilkFX",
srcs: ["**/*.java", "**/*.kt"],
diff --git a/tests/SurfaceViewBufferTests/Android.bp b/tests/SurfaceViewBufferTests/Android.bp
index 48031de..dc75f00 100644
--- a/tests/SurfaceViewBufferTests/Android.bp
+++ b/tests/SurfaceViewBufferTests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "SurfaceViewBufferTests",
srcs: ["**/*.java","**/*.kt"],
diff --git a/tests/UpdatableSystemFontTest/Android.bp b/tests/UpdatableSystemFontTest/Android.bp
index 43a5078..ee24d48 100644
--- a/tests/UpdatableSystemFontTest/Android.bp
+++ b/tests/UpdatableSystemFontTest/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_test_host {
name: "UpdatableSystemFontTest",
srcs: ["src/**/*.java"],
diff --git a/tests/UpdatableSystemFontTest/testdata/Android.bp b/tests/UpdatableSystemFontTest/testdata/Android.bp
index 1296699..f744d5d 100644
--- a/tests/UpdatableSystemFontTest/testdata/Android.bp
+++ b/tests/UpdatableSystemFontTest/testdata/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
filegroup {
name: "UpdatableSystemFontTestKeyPem",
srcs: ["UpdatableSystemFontTestKey.pem"],
diff --git a/tests/benchmarks/internal/Android.bp b/tests/benchmarks/internal/Android.bp
index 9c34eaf..74ed7a3 100644
--- a/tests/benchmarks/internal/Android.bp
+++ b/tests/benchmarks/internal/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
android_test {
name: "InternalBenchTests",
srcs: ["src/**/*.java"],
@@ -23,4 +32,3 @@
platform_apis: true,
certificate: "platform"
}
-
diff --git a/tests/net/common/java/android/net/NetworkStackTest.java b/tests/net/common/java/android/net/NetworkStackTest.java
index a99aa01..f8f9c72 100644
--- a/tests/net/common/java/android/net/NetworkStackTest.java
+++ b/tests/net/common/java/android/net/NetworkStackTest.java
@@ -15,20 +15,8 @@
*/
package android.net;
-import static android.Manifest.permission.NETWORK_STACK;
-import static android.content.pm.PackageManager.PERMISSION_DENIED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
-import static android.net.NetworkStack.checkNetworkStackPermission;
-import static android.net.NetworkStack.checkNetworkStackPermissionOr;
-
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.when;
-import android.content.Context;
import android.os.Build;
import android.os.IBinder;
@@ -46,44 +34,15 @@
@RunWith(AndroidJUnit4.class)
public class NetworkStackTest {
- private static final String [] OTHER_PERMISSION = {"otherpermission1", "otherpermission2"};
-
@Rule
public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule();
- @Mock Context mCtx;
@Mock private IBinder mConnectorBinder;
@Before public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
- @Test
- public void testCheckNetworkStackPermission() throws Exception {
- when(mCtx.checkCallingOrSelfPermission(eq(NETWORK_STACK))).thenReturn(PERMISSION_GRANTED);
- when(mCtx.checkCallingOrSelfPermission(eq(PERMISSION_MAINLINE_NETWORK_STACK)))
- .thenReturn(PERMISSION_DENIED);
- checkNetworkStackPermission(mCtx);
- checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION);
-
- when(mCtx.checkCallingOrSelfPermission(eq(NETWORK_STACK))).thenReturn(PERMISSION_DENIED);
- when(mCtx.checkCallingOrSelfPermission(eq(PERMISSION_MAINLINE_NETWORK_STACK)))
- .thenReturn(PERMISSION_GRANTED);
- checkNetworkStackPermission(mCtx);
- checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION);
-
- when(mCtx.checkCallingOrSelfPermission(any())).thenReturn(PERMISSION_DENIED);
-
- try {
- checkNetworkStackPermissionOr(mCtx, OTHER_PERMISSION);
- } catch (SecurityException e) {
- // Expect to get a SecurityException
- return;
- }
-
- fail("Expect fail but permission granted.");
- }
-
@Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testGetService() {
NetworkStack.setServiceForTest(mConnectorBinder);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 4dbd020..6de1075 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -53,6 +53,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
@@ -2787,7 +2788,8 @@
if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
- capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP) {
+ capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
+ || capability == NET_CAPABILITY_ENTERPRISE) {
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
} else {
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
@@ -2886,6 +2888,7 @@
tryNetworkFactoryRequests(NET_CAPABILITY_IA);
tryNetworkFactoryRequests(NET_CAPABILITY_RCS);
tryNetworkFactoryRequests(NET_CAPABILITY_XCAP);
+ tryNetworkFactoryRequests(NET_CAPABILITY_ENTERPRISE);
tryNetworkFactoryRequests(NET_CAPABILITY_EIMS);
tryNetworkFactoryRequests(NET_CAPABILITY_NOT_METERED);
tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
@@ -6851,7 +6854,7 @@
callback.expectCapabilitiesThat(mMockVpn, (caps)
-> caps.getUids().size() == 2
&& caps.getUids().contains(new UidRange(uid, uid))
- && caps.getUids().contains(UidRange.createForUser(RESTRICTED_USER))
+ && caps.getUids().contains(createUidRange(RESTRICTED_USER))
&& caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_WIFI));
@@ -6861,7 +6864,7 @@
callback.expectCapabilitiesThat(mMockVpn, (caps)
-> caps.getUids().size() == 2
&& caps.getUids().contains(new UidRange(uid, uid))
- && caps.getUids().contains(UidRange.createForUser(RESTRICTED_USER))
+ && caps.getUids().contains(createUidRange(RESTRICTED_USER))
&& caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_WIFI));
@@ -7495,7 +7498,7 @@
assertNotNull(underlying);
mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
// The legacy lockdown VPN only supports userId 0.
- final Set<UidRange> ranges = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+ final Set<UidRange> ranges = Collections.singleton(createUidRange(PRIMARY_USER));
mMockVpn.registerAgent(ranges);
mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
mMockVpn.connect(true);
@@ -8414,7 +8417,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
mMockVpn.establish(lp, VPN_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
@@ -8442,7 +8445,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
@@ -8458,7 +8461,7 @@
lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
@@ -8473,7 +8476,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
mMockVpn.establish(lp, VPN_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
@@ -8525,7 +8528,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final UidRange vpnRange = UidRange.createForUser(PRIMARY_USER);
+ final UidRange vpnRange = createUidRange(PRIMARY_USER);
final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
mMockVpn.establish(lp, VPN_UID, vpnRanges);
assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -8724,7 +8727,7 @@
private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
throws Exception {
- final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
mMockVpn.setVpnType(vpnType);
mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
@@ -9283,7 +9286,7 @@
lp.setInterfaceName("tun0");
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
- final UidRange vpnRange = UidRange.createForUser(PRIMARY_USER);
+ final UidRange vpnRange = createUidRange(PRIMARY_USER);
Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
mMockVpn.establish(lp, VPN_UID, vpnRanges);
assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -10342,4 +10345,8 @@
mEthernetNetworkAgent.getNetwork().netId, 0 /* times */,
true /* shouldDestroyNetwork */);
}
+
+ private UidRange createUidRange(int userId) {
+ return UidRange.createForUser(UserHandle.of(userId));
+ }
}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 6576daf..7489a0f 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -182,7 +182,8 @@
mPackages.put(PKGS[i], PKG_UIDS[i]);
}
}
- private static final UidRange PRI_USER_RANGE = UidRange.createForUser(primaryUser.id);
+ private static final UidRange PRI_USER_RANGE =
+ UidRange.createForUser(UserHandle.of(primaryUser.id));
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
@Mock private UserManager mUserManager;
@@ -272,7 +273,7 @@
vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null);
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- PRI_USER_RANGE, UidRange.createForUser(restrictedProfileA.id)
+ PRI_USER_RANGE, UidRange.createForUser(UserHandle.of(restrictedProfileA.id))
})), ranges);
}
diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
index 7087676..66590c9 100644
--- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
@@ -16,6 +16,8 @@
package android.net.vcn;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
+
import static androidx.test.InstrumentationRegistry.getContext;
import static org.junit.Assert.assertEquals;
@@ -204,10 +206,13 @@
cbBinder.onEnteredSafeMode();
verify(mMockStatusCallback).onEnteredSafeMode();
+ cbBinder.onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
+ verify(mMockStatusCallback).onVcnStatusChanged(VCN_STATUS_CODE_ACTIVE);
+
cbBinder.onGatewayConnectionError(
UNDERLYING_NETWORK_CAPABILITIES,
VcnManager.VCN_ERROR_CODE_NETWORK_ERROR,
- "java.net.UnknownHostException",
+ UnknownHostException.class.getName(),
"exception_message");
verify(mMockStatusCallback)
.onGatewayConnectionError(
diff --git a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java
index 3ba0a1f..a674425 100644
--- a/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnUnderlyingNetworkPolicyTest.java
@@ -46,6 +46,6 @@
@Test
public void testParcelUnparcel() {
- assertParcelSane(SAMPLE_NETWORK_POLICY, 2);
+ assertParcelSane(SAMPLE_NETWORK_POLICY, 1);
}
}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 45b2381..9b500a7 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -43,7 +43,6 @@
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;
@@ -59,6 +58,7 @@
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnConfigTest;
+import android.net.vcn.VcnManager;
import android.net.vcn.VcnUnderlyingNetworkPolicy;
import android.net.wifi.WifiInfo;
import android.os.IBinder;
@@ -783,7 +783,7 @@
true /* hasPermissionsforSubGroup */,
true /* hasLocationPermission */);
- verify(mMockStatusCallback, times(1)).onEnteredSafeMode();
+ verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
}
@Test
@@ -795,7 +795,8 @@
false /* hasPermissionsforSubGroup */,
true /* hasLocationPermission */);
- verify(mMockStatusCallback, never()).onEnteredSafeMode();
+ verify(mMockStatusCallback, never())
+ .onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
}
@Test
@@ -807,7 +808,8 @@
true /* hasPermissionsforSubGroup */,
false /* hasLocationPermission */);
- verify(mMockStatusCallback, never()).onEnteredSafeMode();
+ verify(mMockStatusCallback, never())
+ .onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
}
@Test
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index f0b7595..ebc0ec1 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -11,6 +11,12 @@
EMOJI_VS = 0xFE0F
+#TODO(179952916): Rename CutiveMono and DancingScript
+CANONICAL_NAME_EXCEPTION_LIST = [
+ 'CutiveMono.ttf',
+ 'DancingScript-Regular.ttf',
+]
+
LANG_TO_SCRIPT = {
'as': 'Beng',
'be': 'Cyrl',
@@ -665,6 +671,53 @@
assert_font_supports_none_of_chars(record.font, cjk_punctuation, name)
+def getPostScriptName(font):
+ ttf = open_font(font)
+ nameTable = ttf['name']
+ for name in nameTable.names:
+ if name.nameID == 6 and name.platformID == 3 and name.platEncID == 1 and name.langID == 0x0409:
+ return str(name)
+
+
+def getSuffix(font):
+ file_path, index = font
+ with open(path.join(_fonts_dir, file_path), 'rb') as f:
+ tag = f.read(4)
+ isCollection = tag == b'ttcf'
+
+ ttf = open_font(font)
+ isType1 = ('CFF ' in ttf or 'CFF2' in ttf)
+
+ if isType1:
+ if isCollection:
+ return '.otc'
+ else:
+ return '.otf'
+ else:
+ if isCollection:
+ return '.ttc'
+ else:
+ return '.ttf'
+
+
+def check_canonical_name():
+ for record in _all_fonts:
+ file_name, index = record.font
+ if file_name in CANONICAL_NAME_EXCEPTION_LIST:
+ continue
+
+ if index and index != 0:
+ continue
+
+ psName = getPostScriptName(record.font)
+ assert psName, 'PostScript must be defined'
+
+ suffix = getSuffix(record.font)
+ canonicalName = '%s%s' % (psName, suffix)
+
+ assert file_name == canonicalName, (
+ '%s is not a canonical name. Must be %s' % (file_name, canonicalName))
+
def main():
global _fonts_dir
target_out = sys.argv[1]
@@ -682,6 +735,8 @@
check_cjk_punctuation()
+ check_canonical_name()
+
check_emoji = sys.argv[2]
if check_emoji == 'true':
ucd_path = sys.argv[3]
diff --git a/tools/powerstats/Android.bp b/tools/powerstats/Android.bp
index af41144..9c58daf0 100644
--- a/tools/powerstats/Android.bp
+++ b/tools/powerstats/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_binary_host {
name: "PowerStatsServiceProtoParser",
manifest: "PowerStatsServiceProtoParser_manifest.txt",
diff --git a/tools/processors/intdef_mappings/Android.bp b/tools/processors/intdef_mappings/Android.bp
index e255f7c..82a5dac 100644
--- a/tools/processors/intdef_mappings/Android.bp
+++ b/tools/processors/intdef_mappings/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_plugin {
name: "intdef-annotation-processor",
@@ -30,4 +39,4 @@
],
test_suites: ["general-tests"],
-}
\ No newline at end of file
+}
diff --git a/tools/xmlpersistence/Android.bp b/tools/xmlpersistence/Android.bp
index d58d0dc..0b6dba6 100644
--- a/tools/xmlpersistence/Android.bp
+++ b/tools/xmlpersistence/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
java_binary_host {
name: "xmlpersistence_cli",
manifest: "manifest.txt",