diff options
346 files changed, 8657 insertions, 13334 deletions
diff --git a/Android.bp b/Android.bp index d9fe7cc59261..c47b74717dcd 100644 --- a/Android.bp +++ b/Android.bp @@ -747,6 +747,7 @@ gensrcs { srcs: [ ":ipconnectivity-proto-src", + ":libstats_atom_enum_protos", "core/proto/**/*.proto", "libs/incident/**/*.proto", ], @@ -773,6 +774,7 @@ gensrcs { srcs: [ ":ipconnectivity-proto-src", + ":libstats_atom_enum_protos", "core/proto/**/*.proto", "libs/incident/**/*.proto", ], @@ -912,6 +914,7 @@ java_library_host { name: "platformprotos", srcs: [ ":ipconnectivity-proto-src", + ":libstats_atom_enum_protos", ":libstats_internal_protos", "cmds/am/proto/instrumentation_data.proto", "cmds/statsd/src/**/*.proto", @@ -947,6 +950,7 @@ java_library { sdk_version: "9", srcs: [ ":ipconnectivity-proto-src", + ":libstats_atom_enum_protos", "core/proto/**/*.proto", "libs/incident/proto/android/os/**/*.proto", ], @@ -962,6 +966,7 @@ java_library { srcs: [ ":ipconnectivity-proto-src", + ":libstats_atom_enum_protos", "core/proto/**/*.proto", "libs/incident/proto/android/os/**/*.proto", ], @@ -983,7 +988,9 @@ cc_defaults { proto: { export_proto_headers: true, - include_dirs: ["external/protobuf/src"], + include_dirs: [ + "external/protobuf/src", + ], }, cflags: [ @@ -994,6 +1001,7 @@ cc_defaults { srcs: [ ":ipconnectivity-proto-src", + ":libstats_atom_enum_protos", "core/proto/**/*.proto", ], } diff --git a/core/proto/android/stats/devicepolicy/device_policy.proto b/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.aidl index af30cf3f9941..4686de8df268 100644 --- a/core/proto/android/stats/devicepolicy/device_policy.proto +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.aidl @@ -1,11 +1,11 @@ -/* - * Copyright (C) 2018 The Android Open Source Project +/** + * 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,12 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package android.app.appsearch; -syntax = "proto2"; - -package android.stats.devicepolicy; -option java_multiple_files = true; - -message StringList { - repeated string string_value = 1; -} +/** {@hide} */ +parcelable AppSearchBatchResult;
\ No newline at end of file diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index f2c9942edbb3..e57359fbf50e 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -15,10 +15,12 @@ */ package android.app.appsearch; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.SystemService; import android.content.Context; import android.os.Bundle; +import android.os.ParcelableException; import android.os.RemoteException; import com.android.internal.infra.AndroidFuture; @@ -27,7 +29,10 @@ import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.function.Consumer; /** * This class provides access to the centralized AppSearch index maintained by the system. @@ -40,12 +45,99 @@ import java.util.concurrent.ExecutionException; // TODO(b/148046169): This class header needs a detailed example/tutorial. @SystemService(Context.APP_SEARCH_SERVICE) public class AppSearchManager { - private static final String DEFAULT_DATABASE = ""; + /** + * The default empty database name. + * @hide + */ + public static final String DEFAULT_DATABASE_NAME = ""; + private final IAppSearchManager mService; /** @hide */ public AppSearchManager(@NonNull IAppSearchManager service) { - mService = service; + mService = Objects.requireNonNull(service); + } + + /** Contains information about how to create the search session. */ + public static final class SearchContext { + final String mDatabaseName; + + SearchContext(@NonNull String databaseName) { + mDatabaseName = Objects.requireNonNull(databaseName); + } + + /** + * Returns the name of the database to create or open. + * + * <p>Databases with different names are fully separate with distinct types, namespaces, + * and data. + */ + @NonNull + public String getDatabaseName() { + return mDatabaseName; + } + + /** Builder for {@link SearchContext} objects. */ + public static final class Builder { + private String mDatabaseName = DEFAULT_DATABASE_NAME; + private boolean mBuilt = false; + + /** + * Sets the name of the database associated with {@link AppSearchSession}. + * + * <p>{@link AppSearchSession} will create or open a database under the given name. + * + * <p>Databases with different names are fully separate with distinct types, namespaces, + * and data. + * + * <p>Database name cannot contain {@code '/'}. + * + * <p>If not specified, defaults to {@link #DEFAULT_DATABASE_NAME}. + * @param databaseName The name of the database. + * @throws IllegalArgumentException if the databaseName contains {@code '/'}. + */ + @NonNull + public Builder setDatabaseName(@NonNull String databaseName) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Objects.requireNonNull(databaseName); + if (databaseName.contains("/")) { + throw new IllegalArgumentException("Database name cannot contain '/'"); + } + mDatabaseName = databaseName; + return this; + } + + /** Builds a {@link SearchContext} instance. */ + @NonNull + public SearchContext build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBuilt = true; + return new SearchContext(mDatabaseName); + } + } + } + + /** + * Creates a new {@link AppSearchSession}. + * + * <p>This process requires an AppSearch native indexing file system for each user. If it's not + * created for this user, the initialization process will create one under user's directory. + * + * @param searchContext The {@link SearchContext} contains all information to create a new + * {@link AppSearchSession} + * @param executor Executor on which to invoke the callback. + * @param callback The {@link AppSearchResult}<{@link AppSearchSession}> of + * performing this operation. Or a {@link AppSearchResult} with failure + * reason code and error information. + */ + public void createSearchSession( + @NonNull SearchContext searchContext, + @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<AppSearchResult<AppSearchSession>> callback) { + Objects.requireNonNull(searchContext); + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + AppSearchSession.createSearchSession(searchContext, mService, executor, callback); } /** @@ -99,7 +191,7 @@ public class AppSearchManager { * * @param request The schema update request. * @return the result of performing this operation. - * + * @deprecated use {@link AppSearchSession#setSchema} instead. * @hide */ @NonNull @@ -113,9 +205,14 @@ public class AppSearchManager { } AndroidFuture<AppSearchResult> future = new AndroidFuture<>(); try { - mService.setSchema(DEFAULT_DATABASE, schemaBundles, request.isForceOverride(), future); + mService.setSchema(DEFAULT_DATABASE_NAME, schemaBundles, request.isForceOverride(), + new IAppSearchResultCallback.Stub() { + public void onResult(AppSearchResult result) { + future.complete(result); + } + }); } catch (RemoteException e) { - future.completeExceptionally(e); + throw e.rethrowFromSystemServer(); } return getFutureOrThrow(future); } @@ -134,6 +231,9 @@ public class AppSearchManager { * {@link AppSearchBatchResult} are the URIs of the input documents. The values are * {@code null} if they were successfully indexed, or a failed {@link AppSearchResult} * otherwise. + * @throws RuntimeException If an error occurred during the execution. + * + * @deprecated use {@link AppSearchSession#putDocuments} instead. * @hide */ public AppSearchBatchResult<String, Void> putDocuments(@NonNull PutDocumentsRequest request) { @@ -146,7 +246,16 @@ public class AppSearchManager { } AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>(); try { - mService.putDocuments(DEFAULT_DATABASE, documentBundles, future); + mService.putDocuments(DEFAULT_DATABASE_NAME, documentBundles, + new IAppSearchBatchResultCallback.Stub() { + public void onResult(AppSearchBatchResult result) { + future.complete(result); + } + + public void onSystemError(ParcelableException exception) { + future.completeExceptionally(exception); + } + }); } catch (RemoteException e) { future.completeExceptionally(e); } @@ -165,6 +274,9 @@ public class AppSearchManager { * {@link GenericDocument}s on success, or a failed {@link AppSearchResult} otherwise. * URIs that are not found will return a failed {@link AppSearchResult} with a result code * of {@link AppSearchResult#RESULT_NOT_FOUND}. + * @throws RuntimeException If an error occurred during the execution. + * + * @deprecated use {@link AppSearchSession#getByUri} instead. */ public AppSearchBatchResult<String, GenericDocument> getByUri( @NonNull GetByUriRequest request) { @@ -173,7 +285,16 @@ public class AppSearchManager { List<String> uris = new ArrayList<>(request.getUris()); AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>(); try { - mService.getDocuments(DEFAULT_DATABASE, request.getNamespace(), uris, future); + mService.getDocuments(DEFAULT_DATABASE_NAME, request.getNamespace(), uris, + new IAppSearchBatchResultCallback.Stub() { + public void onResult(AppSearchBatchResult result) { + future.complete(result); + } + + public void onSystemError(ParcelableException exception) { + future.completeExceptionally(exception); + } + }); } catch (RemoteException e) { future.completeExceptionally(e); } @@ -252,6 +373,9 @@ public class AppSearchManager { * * @param queryExpression Query String to search. * @param searchSpec Spec for setting filters, raw query etc. + * @throws RuntimeException If an error occurred during the execution. + * + * @deprecated use AppSearchSession#query instead. * @hide */ @NonNull @@ -261,7 +385,7 @@ public class AppSearchManager { // them in one big list. AndroidFuture<AppSearchResult> searchResultsFuture = new AndroidFuture<>(); try { - mService.query(DEFAULT_DATABASE, queryExpression, + mService.query(DEFAULT_DATABASE_NAME, queryExpression, searchSpec.getBundle(), searchResultsFuture); } catch (RemoteException e) { searchResultsFuture.completeExceptionally(e); @@ -278,7 +402,7 @@ public class AppSearchManager { } /** - * Deletes {@link GenericDocument}s by URI. + * Removes {@link GenericDocument}s by URI. * * <p>You should not call this method directly; instead, use the {@code AppSearch#delete()} API * provided by JetPack. @@ -289,12 +413,24 @@ public class AppSearchManager { * or a failed {@link AppSearchResult} otherwise. URIs that are not found will return a * failed {@link AppSearchResult} with a result code of * {@link AppSearchResult#RESULT_NOT_FOUND}. + * @throws RuntimeException If an error occurred during the execution. + * + * @deprecated use {@link AppSearchSession#removeByUri} instead. */ public AppSearchBatchResult<String, Void> removeByUri(@NonNull RemoveByUriRequest request) { List<String> uris = new ArrayList<>(request.getUris()); AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>(); try { - mService.removeByUri(DEFAULT_DATABASE, request.getNamespace(), uris, future); + mService.removeByUri(DEFAULT_DATABASE_NAME, request.getNamespace(), uris, + new IAppSearchBatchResultCallback.Stub() { + public void onResult(AppSearchBatchResult result) { + future.complete(result); + } + + public void onSystemError(ParcelableException exception) { + future.completeExceptionally(exception); + } + }); } catch (RemoteException e) { future.completeExceptionally(e); } diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.aidl b/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.aidl new file mode 100644 index 000000000000..f0b29964b895 --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.aidl @@ -0,0 +1,19 @@ +/** + * Copyright 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.app.appsearch; + +/** {@hide} */ +parcelable AppSearchResult;
\ No newline at end of file diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java index 979eab90a980..6e2ed70cca01 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java @@ -19,9 +19,11 @@ package android.app.appsearch; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.appsearch.exceptions.AppSearchException; import android.os.Parcel; import android.os.Parcelable; +import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; @@ -218,4 +220,25 @@ public final class AppSearchResult<ValueType> implements Parcelable { @ResultCode int resultCode, @Nullable String errorMessage) { return new AppSearchResult<>(resultCode, /*resultValue=*/ null, errorMessage); } + + /** @hide */ + @NonNull + public static <ValueType> AppSearchResult<ValueType> throwableToFailedResult( + @NonNull Throwable t) { + if (t instanceof AppSearchException) { + return ((AppSearchException) t).toAppSearchResult(); + } + + @AppSearchResult.ResultCode int resultCode; + if (t instanceof IllegalStateException) { + resultCode = AppSearchResult.RESULT_INTERNAL_ERROR; + } else if (t instanceof IllegalArgumentException) { + resultCode = AppSearchResult.RESULT_INVALID_ARGUMENT; + } else if (t instanceof IOException) { + resultCode = AppSearchResult.RESULT_IO_ERROR; + } else { + resultCode = AppSearchResult.RESULT_UNKNOWN_ERROR; + } + return AppSearchResult.newFailedResult(resultCode, t.toString()); + } } diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java new file mode 100644 index 000000000000..531436ecaf0c --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java @@ -0,0 +1,312 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.appsearch; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.app.appsearch.exceptions.AppSearchException; +import android.os.Bundle; +import android.os.ParcelableException; +import android.os.RemoteException; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +/** + * Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be + * placed and queried. + * @hide + */ +public final class AppSearchSession { + private final String mDatabaseName; + private final IAppSearchManager mService; + + static void createSearchSession( + @NonNull AppSearchManager.SearchContext searchContext, + @NonNull IAppSearchManager service, + @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<AppSearchResult<AppSearchSession>> callback) { + AppSearchSession searchSession = + new AppSearchSession(searchContext.mDatabaseName, service); + searchSession.initialize(executor, callback); + } + + // NOTE: No instance of this class should be created or returned except via initialize(). + // Once the callback.accept has been called here, the class is ready to use. + private void initialize( + @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<AppSearchResult<AppSearchSession>> callback) { + try { + mService.initialize(new IAppSearchResultCallback.Stub() { + public void onResult(AppSearchResult result) { + executor.execute(() -> { + if (result.isSuccess()) { + callback.accept( + AppSearchResult.newSuccessfulResult(AppSearchSession.this)); + } else { + callback.accept(result); + } + }); + } + }); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private AppSearchSession(@NonNull String databaseName, @NonNull IAppSearchManager service) { + mDatabaseName = databaseName; + mService = service; + } + + /** + * Sets the schema will be used by documents provided to the {@link #putDocuments} method. + * + * <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: + * <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 returning an + * {@link AppSearchResult} with a code of {@link AppSearchResult#RESULT_INVALID_SCHEMA} and an + * error 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 set the + * {@link SetSchemaRequest.Builder#setForceOverride} method to {@code true}. In this case, + * instead of returning an {@link AppSearchResult} 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. + * + * <p>It is a no-op to set the same schema as has been previously set; this is handled + * efficiently. + * + * @param request The schema update request. + * @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}. + */ + public void setSchema( + @NonNull SetSchemaRequest request, + @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<AppSearchResult<Void>> callback) { + Objects.requireNonNull(request); + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + List<Bundle> schemaBundles = new ArrayList<>(request.getSchemas().size()); + for (AppSearchSchema schema : request.getSchemas()) { + schemaBundles.add(schema.getBundle()); + } + try { + mService.setSchema(mDatabaseName, schemaBundles, request.isForceOverride(), + new IAppSearchResultCallback.Stub() { + public void onResult(AppSearchResult result) { + executor.execute(() -> callback.accept(result)); + } + }); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Indexes documents into AppSearch. + * + * <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. + * + * @param request {@link PutDocumentsRequest} 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 + * documents. The values are {@code null} if they were successfully indexed, + * or a failed {@link AppSearchResult} otherwise. + * Or {@link BatchResultCallback#onSystemError} will be invoked with an + * {@link AppSearchException} if an error occurred in AppSearch initialization + * or a cause {@link Throwable} if other error occurred in AppSearch service. + */ + public void putDocuments( + @NonNull PutDocumentsRequest request, + @NonNull @CallbackExecutor Executor executor, + @NonNull BatchResultCallback<String, Void> callback) { + Objects.requireNonNull(request); + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + List<GenericDocument> documents = request.getDocuments(); + List<Bundle> documentBundles = new ArrayList<>(documents.size()); + for (int i = 0; i < documents.size(); i++) { + documentBundles.add(documents.get(i).getBundle()); + } + try { + mService.putDocuments(mDatabaseName, documentBundles, + new IAppSearchBatchResultCallback.Stub() { + public void onResult(AppSearchBatchResult result) { + executor.execute(() -> callback.onResult(result)); + } + + public void onSystemError(ParcelableException exception) { + executor.execute(() -> callback.onSystemError(exception.getCause())); + } + }); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieves {@link GenericDocument}s by URI. + * + * @param request {@link GetByUriRequest} containing URIs to be retrieved. + * @param executor Executor on which to invoke the callback. + * @param callback Callback to receive the pending result of performing this operation. The keys + * of the returned {@link AppSearchBatchResult} are the input URIs. The values + * are the returned {@link GenericDocument}s on success, or a failed + * {@link AppSearchResult} otherwise. URIs that are not found will return a + * failed {@link AppSearchResult} with a result code of + * {@link AppSearchResult#RESULT_NOT_FOUND}. + * Or {@link BatchResultCallback#onSystemError} will be invoked with an + * {@link AppSearchException} if an error occurred in AppSearch initialization + * or a cause {@link Throwable} if other error occurred in AppSearch service. + */ + public void getByUri( + @NonNull GetByUriRequest request, + @NonNull @CallbackExecutor Executor executor, + @NonNull BatchResultCallback<String, GenericDocument> callback) { + Objects.requireNonNull(request); + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + try { + mService.getDocuments(mDatabaseName, request.getNamespace(), + new ArrayList<>(request.getUris()), + new IAppSearchBatchResultCallback.Stub() { + public void onResult(AppSearchBatchResult result) { + executor.execute(() -> { + AppSearchBatchResult.Builder<String, GenericDocument> + documentResultBuilder = + new AppSearchBatchResult.Builder<>(); + + // Translate successful results + for (Map.Entry<String, Bundle> bundleEntry : + (Set<Map.Entry<String, Bundle>>) + result.getSuccesses().entrySet()) { + GenericDocument document; + try { + document = new GenericDocument(bundleEntry.getValue()); + } catch (Throwable t) { + // These documents went through validation, so how could + // this fail? We must have done something wrong. + documentResultBuilder.setFailure( + bundleEntry.getKey(), + AppSearchResult.RESULT_INTERNAL_ERROR, + t.getMessage()); + continue; + } + documentResultBuilder.setSuccess( + bundleEntry.getKey(), document); + } + + // Translate failed results + for (Map.Entry<String, AppSearchResult<Bundle>> bundleEntry : + (Set<Map.Entry<String, AppSearchResult<Bundle>>>) + result.getFailures().entrySet()) { + documentResultBuilder.setFailure( + bundleEntry.getKey(), + bundleEntry.getValue().getResultCode(), + bundleEntry.getValue().getErrorMessage()); + } + callback.onResult(documentResultBuilder.build()); + }); + } + + public void onSystemError(ParcelableException exception) { + executor.execute(() -> callback.onSystemError(exception.getCause())); + } + }); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Removes {@link GenericDocument}s from the index by URI. + * + * @param request Request containing URIs to be removed. + * @param executor Executor on which to invoke the callback. + * @param callback Callback to receive the pending result of performing this operation. The keys + * of the returned {@link AppSearchBatchResult} are the input URIs. The values + * are {@code null} on success, or a failed {@link AppSearchResult} otherwise. + * URIs that are not found will return a failed {@link AppSearchResult} with a + * result code of {@link AppSearchResult#RESULT_NOT_FOUND}. + * Or {@link BatchResultCallback#onSystemError} will be invoked with an + * {@link AppSearchException} if an error occurred in AppSearch initialization + * or a cause {@link Throwable} if other error occurred in AppSearch service. + */ + public void removeByUri( + @NonNull RemoveByUriRequest request, + @NonNull @CallbackExecutor Executor executor, + @NonNull BatchResultCallback<String, Void> callback) { + Objects.requireNonNull(request); + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + try { + mService.removeByUri(mDatabaseName, request.getNamespace(), + new ArrayList<>(request.getUris()), + new IAppSearchBatchResultCallback.Stub() { + public void onResult(AppSearchBatchResult result) { + executor.execute(() -> callback.onResult(result)); + } + + public void onSystemError(ParcelableException exception) { + executor.execute(() -> callback.onSystemError(exception.getCause())); + } + }); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + // TODO(b/162450968) port query() and SearchResults.java to platform. + // TODO(b/162450968) port removeByQuery() to platform. +} diff --git a/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java b/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java new file mode 100644 index 000000000000..1689e02c7ce4 --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.appsearch; + +/** + * The callback interface to return {@link AppSearchBatchResult}. + * + * @param <KeyType> The type of the keys for {@link AppSearchBatchResult#getSuccesses} and + * {@link AppSearchBatchResult#getFailures}. + * @param <ValueType> The type of result objects associated with the keys. + * @hide + */ +public interface BatchResultCallback<KeyType, ValueType> { + + /** + * Called when {@link AppSearchBatchResult} results are ready. + * + * @param result The result of the executed request. + */ + void onResult(AppSearchBatchResult<KeyType, ValueType> result); + + + /** + * Called when a system error occurred. + * + * @param throwable The cause throwable. + */ + default void onSystemError(Throwable throwable) { + if (throwable != null) { + throw new RuntimeException(throwable); + } + } +} diff --git a/core/proto/android/stats/mediaprovider/mediaprovider_enums.proto b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchBatchResultCallback.aidl index 138782bf5d19..b1bbd18b98e2 100644 --- a/core/proto/android/stats/mediaprovider/mediaprovider_enums.proto +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchBatchResultCallback.aidl @@ -1,11 +1,11 @@ -/* - * Copyright (C) 2019 The Android Open Source Project +/** + * 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,18 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package android.app.appsearch; -syntax = "proto2"; -package android.stats.mediaprovider; -option java_multiple_files = true; +import android.app.appsearch.AppSearchBatchResult; +import android.os.ParcelableException; -enum VolumeType { - // Volume is unknown - UNKNOWN = 0; - // Volume is MediaStore.VOLUME_INTERNAL - INTERNAL = 1; - // Volume is MediaStore.VOLUME_EXTERNAL_PRIMARY - EXTERNAL_PRIMARY = 2; - // Volume is non-primary external storage - EXTERNAL_OTHER = 3; -} +/** {@hide} */ +oneway interface IAppSearchBatchResultCallback { + void onResult(in AppSearchBatchResult result); + void onSystemError(in ParcelableException exception); +}
\ No newline at end of file diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl index 01260ea193f6..4a981022da73 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl @@ -17,10 +17,12 @@ package android.app.appsearch; import android.os.Bundle; +import android.app.appsearch.AppSearchBatchResult; +import android.app.appsearch.AppSearchResult; +import android.app.appsearch.IAppSearchBatchResultCallback; +import android.app.appsearch.IAppSearchResultCallback; import com.android.internal.infra.AndroidFuture; -parcelable AppSearchResult; -parcelable AppSearchBatchResult; parcelable SearchResults; /** {@hide} */ @@ -32,14 +34,14 @@ interface IAppSearchManager { * @param schemaBundles List of AppSearchSchema bundles. * @param forceOverride Whether to apply the new schema even if it is incompatible. All * incompatible documents will be deleted. - * @param callback {@link AndroidFuture}<{@link AppSearchResult}<{@link Void}>>. - * The results of the call. + * @param callback {@link IAppSearchResultCallback#onResult} will be called with an + * {@link AppSearchResult}<{@link Void}>. */ void setSchema( in String databaseName, in List<Bundle> schemaBundles, boolean forceOverride, - in AndroidFuture<AppSearchResult> callback); + in IAppSearchResultCallback callback); /** * Inserts documents into the index. @@ -47,16 +49,16 @@ interface IAppSearchManager { * @param databaseName The name of the database where this document lives. * @param documentBundes List of GenericDocument bundles. * @param callback - * {@link AndroidFuture}<{@link AppSearchBatchResult}<{@link String}, {@link Void}>>. - * If the call fails to start, {@code callback} will be completed exceptionally. Otherwise, - * {@code callback} will be completed with an + * If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError} + * will be called with the cause throwable. Otherwise, + * {@link IAppSearchBatchResultCallback#onResult} will be called with an * {@link AppSearchBatchResult}<{@link String}, {@link Void}> * where the keys are document URIs, and the values are {@code null}. */ void putDocuments( in String databaseName, in List<Bundle> documentBundles, - in AndroidFuture<AppSearchBatchResult> callback); + in IAppSearchBatchResultCallback callback); /** * Retrieves documents from the index. @@ -65,9 +67,9 @@ interface IAppSearchManager { * @param namespace The namespace this document resides in. * @param uris The URIs of the documents to retrieve * @param callback - * {@link AndroidFuture}<{@link AppSearchBatchResult}<{@link String}, {@link Bundle}>>. - * If the call fails to start, {@code callback} will be completed exceptionally. Otherwise, - * {@code callback} will be completed with an + * If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError} + * will be called with the cause throwable. Otherwise, + * {@link IAppSearchBatchResultCallback#onResult} will be called with an * {@link AppSearchBatchResult}<{@link String}, {@link Bundle}> * where the keys are document URIs, and the values are Document bundles. */ @@ -75,7 +77,7 @@ interface IAppSearchManager { in String databaseName, in String namespace, in List<String> uris, - in AndroidFuture<AppSearchBatchResult> callback); + in IAppSearchBatchResultCallback callback); /** * Searches a document based on a given specifications. @@ -98,9 +100,9 @@ interface IAppSearchManager { * @param namespace Namespace of the document to remove. * @param uris The URIs of the documents to delete * @param callback - * {@link AndroidFuture}<{@link AppSearchBatchResult}<{@link String}, {@link Void}>>. - * If the call fails to start, {@code callback} will be completed exceptionally. Otherwise, - * {@code callback} will be completed with an + * If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError} + * will be called with the cause throwable. Otherwise, + * {@link IAppSearchBatchResultCallback#onResult} will be called with an * {@link AppSearchBatchResult}<{@link String}, {@link Void}> * where the keys are document URIs. If a document doesn't exist, it will be reported as a * failure where the {@code throwable} is {@code null}. @@ -109,7 +111,7 @@ interface IAppSearchManager { in String databaseName, in String namespace, in List<String> uris, - in AndroidFuture<AppSearchBatchResult> callback); + in IAppSearchBatchResultCallback callback); /** * Removes documents by given query. @@ -124,4 +126,12 @@ interface IAppSearchManager { in String queryExpression, in Bundle searchSpecBundle, in AndroidFuture<AppSearchResult> callback); + + /** + * Creates and initializes AppSearchImpl for the calling app. + * + * @param callback {@link IAppSearchResultCallback#onResult} will be called with an + * {@link AppSearchResult}<{@link Void}>. + */ + void initialize(in IAppSearchResultCallback callback); } diff --git a/core/proto/android/bluetooth/hfp/enums.proto b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchResultCallback.aidl index d286e4b64d67..27729a5ad058 100644 --- a/core/proto/android/bluetooth/hfp/enums.proto +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchResultCallback.aidl @@ -1,11 +1,11 @@ -/* - * Copyright 2018 The Android Open Source Project +/** + * 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,16 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package android.app.appsearch; -syntax = "proto2"; -package android.bluetooth.hfp; +import android.app.appsearch.AppSearchResult; +import android.os.ParcelableException; -option java_outer_classname = "BluetoothHfpProtoEnums"; -option java_multiple_files = true; - -enum ScoCodec { - SCO_CODEC_UNKNOWN = 0; - SCO_CODEC_CVSD = 1; - // Default codec behind Wide Band Speech - SCO_CODEC_MSBC = 2; +/** {@hide} */ +oneway interface IAppSearchResultCallback { + void onResult(in AppSearchResult result); }
\ No newline at end of file diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index 1dfde528e69b..8269799d5a0d 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -15,27 +15,32 @@ */ package com.android.server.appsearch; +import static android.app.appsearch.AppSearchResult.throwableToFailedResult; + import android.annotation.NonNull; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchResult; import android.app.appsearch.AppSearchSchema; import android.app.appsearch.GenericDocument; +import android.app.appsearch.IAppSearchBatchResultCallback; import android.app.appsearch.IAppSearchManager; +import android.app.appsearch.IAppSearchResultCallback; import android.app.appsearch.SearchResultPage; import android.app.appsearch.SearchSpec; -import android.app.appsearch.exceptions.AppSearchException; import android.content.Context; import android.os.Binder; import android.os.Bundle; +import android.os.ParcelableException; +import android.os.RemoteException; import android.os.UserHandle; import android.util.ArraySet; +import android.util.Log; import com.android.internal.infra.AndroidFuture; import com.android.internal.util.Preconditions; import com.android.server.SystemService; import com.android.server.appsearch.external.localstorage.AppSearchImpl; -import java.io.IOException; import java.util.List; import java.util.Set; @@ -61,10 +66,9 @@ public class AppSearchManagerService extends SystemService { @NonNull String databaseName, @NonNull List<Bundle> schemaBundles, boolean forceOverride, - @NonNull AndroidFuture<AppSearchResult> callback) { + @NonNull IAppSearchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(schemaBundles); - Preconditions.checkNotNull(callback); int callingUid = Binder.getCallingUidOrThrow(); int callingUserId = UserHandle.getUserId(callingUid); final long callingIdentity = Binder.clearCallingIdentity(); @@ -76,9 +80,10 @@ public class AppSearchManagerService extends SystemService { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); impl.setSchema(databaseName, schemas, forceOverride); - callback.complete(AppSearchResult.newSuccessfulResult(/*result=*/ null)); + invokeCallbackOnResult(callback, + AppSearchResult.newSuccessfulResult(/*result=*/ null)); } catch (Throwable t) { - callback.complete(throwableToFailedResult(t)); + invokeCallbackOnError(callback, t); } finally { Binder.restoreCallingIdentity(callingIdentity); } @@ -88,7 +93,7 @@ public class AppSearchManagerService extends SystemService { public void putDocuments( @NonNull String databaseName, @NonNull List<Bundle> documentBundles, - @NonNull AndroidFuture<AppSearchBatchResult> callback) { + @NonNull IAppSearchBatchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(documentBundles); Preconditions.checkNotNull(callback); @@ -96,22 +101,24 @@ public class AppSearchManagerService extends SystemService { int callingUserId = UserHandle.getUserId(callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { - AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); AppSearchBatchResult.Builder<String, Void> resultBuilder = new AppSearchBatchResult.Builder<>(); + AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); for (int i = 0; i < documentBundles.size(); i++) { GenericDocument document = new GenericDocument(documentBundles.get(i)); try { + // TODO(b/173451571): reduce burden of binder thread by enqueue request onto + // a separate thread. impl.putDocument(databaseName, document); resultBuilder.setSuccess(document.getUri(), /*result=*/ null); } catch (Throwable t) { resultBuilder.setResult(document.getUri(), throwableToFailedResult(t)); } } - callback.complete(resultBuilder.build()); + invokeCallbackOnResult(callback, resultBuilder.build()); } catch (Throwable t) { - callback.completeExceptionally(t); + invokeCallbackOnError(callback, t); } finally { Binder.restoreCallingIdentity(callingIdentity); } @@ -119,7 +126,8 @@ public class AppSearchManagerService extends SystemService { @Override public void getDocuments(@NonNull String databaseName, @NonNull String namespace, - @NonNull List<String> uris, @NonNull AndroidFuture<AppSearchBatchResult> callback) { + @NonNull List<String> uris, + @NonNull IAppSearchBatchResultCallback callback) { Preconditions.checkNotNull(databaseName); Preconditions.checkNotNull(namespace); Preconditions.checkNotNull(uris); @@ -128,10 +136,10 @@ public class AppSearchManagerService extends SystemService { int callingUserId = UserHandle.getUserId(callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { - AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); - databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); AppSearchBatchResult.Builder<String, Bundle> resultBuilder = new AppSearchBatchResult.Builder<>(); + AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); for (int i = 0; i < uris.size(); i++) { String uri = uris.get(i); try { @@ -141,9 +149,9 @@ public class AppSearchManagerService extends SystemService { resultBuilder.setResult(uri, throwableToFailedResult(t)); } } - callback.complete(resultBuilder.build()); + invokeCallbackOnResult(callback, resultBuilder.build()); } catch (Throwable t) { - callback.completeExceptionally(t); + invokeCallbackOnError(callback, t); } finally { Binder.restoreCallingIdentity(callingIdentity); } @@ -182,19 +190,19 @@ public class AppSearchManagerService extends SystemService { @Override public void removeByUri(@NonNull String databaseName, @NonNull String namespace, - List<String> uris, AndroidFuture<AppSearchBatchResult> callback) { + @NonNull List<String> uris, + @NonNull IAppSearchBatchResultCallback callback) { Preconditions.checkNotNull(databaseName); - Preconditions.checkNotNull(namespace); Preconditions.checkNotNull(uris); Preconditions.checkNotNull(callback); int callingUid = Binder.getCallingUidOrThrow(); int callingUserId = UserHandle.getUserId(callingUid); final long callingIdentity = Binder.clearCallingIdentity(); + AppSearchBatchResult.Builder<String, Void> resultBuilder = + new AppSearchBatchResult.Builder<>(); try { AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); - AppSearchBatchResult.Builder<String, Void> resultBuilder = - new AppSearchBatchResult.Builder<>(); for (int i = 0; i < uris.size(); i++) { String uri = uris.get(i); try { @@ -204,9 +212,9 @@ public class AppSearchManagerService extends SystemService { resultBuilder.setResult(uri, throwableToFailedResult(t)); } } - callback.complete(resultBuilder.build()); + invokeCallbackOnResult(callback, resultBuilder.build()); } catch (Throwable t) { - callback.completeExceptionally(t); + invokeCallbackOnError(callback, t); } finally { Binder.restoreCallingIdentity(callingIdentity); } @@ -237,6 +245,21 @@ public class AppSearchManagerService extends SystemService { } } + @Override + public void initialize(@NonNull IAppSearchResultCallback callback) { + int callingUid = Binder.getCallingUidOrThrow(); + int callingUserId = UserHandle.getUserId(callingUid); + final long callingIdentity = Binder.clearCallingIdentity(); + try { + ImplInstanceManager.getInstance(getContext(), callingUserId); + invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null)); + } catch (Throwable t) { + invokeCallbackOnError(callback, t); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + } + /** * Rewrites the database name by adding a prefix of unique name for the given uid. * @@ -256,23 +279,51 @@ public class AppSearchManagerService extends SystemService { return callingUidName + CALLING_NAME_DATABASE_DELIMITER + databaseName; } - private <ValueType> AppSearchResult<ValueType> throwableToFailedResult( - @NonNull Throwable t) { - if (t instanceof AppSearchException) { - return ((AppSearchException) t).toAppSearchResult(); + /** Invokes the {@link IAppSearchResultCallback} with the result. */ + private void invokeCallbackOnResult(IAppSearchResultCallback callback, + AppSearchResult result) { + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.d(TAG, "Unable to send result to the callback", e); } + } - @AppSearchResult.ResultCode int resultCode; - if (t instanceof IllegalStateException) { - resultCode = AppSearchResult.RESULT_INTERNAL_ERROR; - } else if (t instanceof IllegalArgumentException) { - resultCode = AppSearchResult.RESULT_INVALID_ARGUMENT; - } else if (t instanceof IOException) { - resultCode = AppSearchResult.RESULT_IO_ERROR; - } else { - resultCode = AppSearchResult.RESULT_UNKNOWN_ERROR; + /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */ + private void invokeCallbackOnResult(IAppSearchBatchResultCallback callback, + AppSearchBatchResult result) { + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.d(TAG, "Unable to send result to the callback", e); + } + } + + /** + * Invokes the {@link IAppSearchResultCallback} with an throwable. + * + * <p>The throwable is convert to a {@link AppSearchResult}; + */ + private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) { + try { + callback.onResult(throwableToFailedResult(throwable)); + } catch (RemoteException e) { + Log.d(TAG, "Unable to send result to the callback", e); + } + } + + /** + * Invokes the {@link IAppSearchBatchResultCallback} with an throwable. + * + * <p>The throwable is converted to {@link ParcelableException}. + */ + private void invokeCallbackOnError(IAppSearchBatchResultCallback callback, + Throwable throwable) { + try { + callback.onSystemError(new ParcelableException(throwable)); + } catch (RemoteException e) { + Log.d(TAG, "Unable to send error to the callback", e); } - return AppSearchResult.newFailedResult(resultCode, t.getMessage()); } } } diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 046145f90808..3b4823e799ce 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -605,6 +605,7 @@ bool BootAnimation::threadLoop() { result = movie(); } + mCallbacks->shutdown(); eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(mDisplay, mContext); eglDestroySurface(mDisplay, mSurface); @@ -691,7 +692,6 @@ void BootAnimation::checkExit() { int exitnow = atoi(value); if (exitnow) { requestExit(); - mCallbacks->shutdown(); } } diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp index 41bdff8a464c..bde59f497b19 100644 --- a/cmds/statsd/tests/LogEvent_test.cpp +++ b/cmds/statsd/tests/LogEvent_test.cpp @@ -16,8 +16,8 @@ #include <gtest/gtest.h> -#include "frameworks/base/core/proto/android/stats/launcher/launcher.pb.h" #include "frameworks/proto_logging/stats/atoms.pb.h" +#include "frameworks/proto_logging/stats/enums/stats/launcher/launcher.pb.h" #include "log/log_event_list.h" #include "stats_event.h" diff --git a/core/api/current.txt b/core/api/current.txt index 01c2b625ead6..e302b25873b4 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -40978,6 +40978,19 @@ package android.se.omapi { package android.security { + public final class AppUriAuthenticationPolicy implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public java.util.Map<java.lang.String,java.util.Map<android.net.Uri,java.lang.String>> getAppAndUriMappings(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.security.AppUriAuthenticationPolicy> CREATOR; + } + + public static final class AppUriAuthenticationPolicy.Builder { + ctor public AppUriAuthenticationPolicy.Builder(); + method @NonNull public android.security.AppUriAuthenticationPolicy.Builder addAppAndUriMapping(@NonNull String, @NonNull android.net.Uri, @NonNull String); + method @NonNull public android.security.AppUriAuthenticationPolicy build(); + } + public final class AttestedKeyPair { ctor public AttestedKeyPair(@Nullable java.security.KeyPair, @NonNull java.util.List<java.security.cert.Certificate>); method @NonNull public java.util.List<java.security.cert.Certificate> getAttestationRecord(); @@ -41025,6 +41038,7 @@ package android.security { method public static void choosePrivateKeyAlias(@NonNull android.app.Activity, @NonNull android.security.KeyChainAliasCallback, @Nullable String[], @Nullable java.security.Principal[], @Nullable String, int, @Nullable String); method public static void choosePrivateKeyAlias(@NonNull android.app.Activity, @NonNull android.security.KeyChainAliasCallback, @Nullable String[], @Nullable java.security.Principal[], @Nullable android.net.Uri, @Nullable String); 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 @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); @@ -44555,6 +44569,7 @@ package android.telecom { method public android.telecom.PhoneAccount.Builder toBuilder(); method public void writeToParcel(android.os.Parcel, int); field public static final int CAPABILITY_ADHOC_CONFERENCE_CALLING = 16384; // 0x4000 + field public static final int CAPABILITY_CALL_COMPOSER = 32768; // 0x8000 field public static final int CAPABILITY_CALL_PROVIDER = 2; // 0x2 field public static final int CAPABILITY_CALL_SUBJECT = 64; // 0x40 field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1 diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 7d82f43af975..99179ec89cbc 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -6693,6 +6693,7 @@ package android.net { method public final void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities); method public final void sendNetworkScore(@IntRange(from=0, to=99) int); method public final void sendSocketKeepaliveEvent(int, int); + method public final void setUnderlyingNetworks(@Nullable java.util.List<android.net.Network>); method public void unregister(); field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2 field public static final int VALIDATION_STATUS_VALID = 1; // 0x1 diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 52a79bae6324..5434bcca0575 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -832,6 +832,14 @@ package android.hardware.soundtrigger { } +package android.inputmethodservice { + + public class InputMethodService extends android.inputmethodservice.AbstractInputMethodService { + field public static final long FINISH_INPUT_NO_FALLBACK_CONNECTION = 156215187L; // 0x94fa793L + } + +} + package android.location { public final class GnssClock implements android.os.Parcelable { @@ -2082,12 +2090,15 @@ package android.view { } public interface WindowManager extends android.view.ViewManager { + method public default int getDisplayImePolicy(int); method public default void holdLock(android.os.IBinder, int); - method public default void setShouldShowIme(int, boolean); + method public default void setDisplayImePolicy(int, int); method public default void setShouldShowSystemDecors(int, boolean); method public default void setShouldShowWithInsecureKeyguard(int, boolean); - method public default boolean shouldShowIme(int); method public default boolean shouldShowSystemDecors(int); + field public static final int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1; // 0x1 + field public static final int DISPLAY_IME_POLICY_HIDE = 2; // 0x2 + field public static final int DISPLAY_IME_POLICY_LOCAL = 0; // 0x0 } public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable { diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java index 862563706da7..a60e6428418d 100644 --- a/core/java/android/content/pm/SharedLibraryInfo.java +++ b/core/java/android/content/pm/SharedLibraryInfo.java @@ -114,15 +114,6 @@ public final class SharedLibraryInfo implements Parcelable { mIsNative = isNative; } - /** @hide */ - public SharedLibraryInfo(String path, String packageName, List<String> codePaths, - String name, long version, int type, - VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages, - List<SharedLibraryInfo> dependencies) { - this(path, packageName, codePaths, name, version, type, declaringPackage, dependentPackages, - dependencies, false /* isNative */); - } - private SharedLibraryInfo(Parcel parcel) { mPath = parcel.readString8(); mPackageName = parcel.readString8(); diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 7fb73ceab4f4..81ea2f5a17dd 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -56,6 +56,7 @@ import android.view.PointerIcon; import android.view.VerifiedInputEvent; import android.view.WindowManager.LayoutParams; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import com.android.internal.util.ArrayUtils; @@ -275,6 +276,21 @@ public final class InputManager { * * @hide */ + @VisibleForTesting + public static InputManager resetInstance(IInputManager inputManagerService) { + synchronized (InputManager.class) { + sInstance = new InputManager(inputManagerService); + return sInstance; + } + } + + /** + * Gets an instance of the input manager. + * + * @return The input manager instance. + * + * @hide + */ @UnsupportedAppUsage public static InputManager getInstance() { synchronized (InputManager.class) { @@ -1428,7 +1444,7 @@ public final class InputManager { @Override public boolean hasAmplitudeControl() { - return false; + return true; } /** diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java index e9de27456f97..0766917642e8 100644 --- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java @@ -54,6 +54,8 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub private static final int DO_VIEW_CLICKED = 115; private static final int DO_NOTIFY_IME_HIDDEN = 120; private static final int DO_REMOVE_IME_SURFACE = 130; + private static final int DO_FINISH_INPUT = 140; + @UnsupportedAppUsage HandlerCaller mCaller; @@ -141,6 +143,10 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub mInputMethodSession.removeImeSurface(); return; } + case DO_FINISH_INPUT: { + mInputMethodSession.finishInput(); + return; + } } Log.w(TAG, "Unhandled message code: " + msg.what); } @@ -222,6 +228,10 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_SESSION)); } + @Override + public void finishInput() { + mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_INPUT)); + } private final class ImeInputEventReceiver extends InputEventReceiver implements InputMethodSession.EventCallback { private final SparseArray<InputEvent> mPendingEvents = new SparseArray<InputEvent>(); diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index ae260e16806f..4a5d831cd705 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -61,9 +61,12 @@ import android.annotation.IntDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.TestApi; import android.annotation.UiContext; import android.app.ActivityManager; import android.app.Dialog; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.PackageManager; @@ -411,7 +414,29 @@ public class InputMethodService extends AbstractInputMethodService { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) int mTheme = 0; - + + /** + * Finish the {@link InputConnection} when the device becomes + * {@link android.os.PowerManager#isInteractive non-interactive}. + * + * <p> + * If enabled by the current {@link InputMethodService input method}, the current input + * connection will be {@link InputMethodService#onFinishInput finished} whenever the devices + * becomes non-interactive. + * + * <p> + * If not enabled, the current input connection will instead be silently deactivated when the + * devices becomes non-interactive, and an {@link InputMethodService#onFinishInput + * onFinishInput()} {@link InputMethodService#onStartInput onStartInput()} pair is dispatched + * when the device becomes interactive again. + * + * @hide + */ + @TestApi + @ChangeId + @EnabledSince(targetSdkVersion = Build.VERSION_CODES.S) + public static final long FINISH_INPUT_NO_FALLBACK_CONNECTION = 156215187L; // This is a bug id. + LayoutInflater mInflater; TypedArray mThemeAttrs; @UnsupportedAppUsage @@ -2325,7 +2350,7 @@ public class InputMethodService extends AbstractInputMethodService { } void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) { - if (!restarting) { + if (!restarting && mInputStarted) { doFinishInput(); } ImeTracing.getInstance().triggerServiceDump("InputMethodService#doStartInput", this); diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java b/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java index dbb669be1402..2db9ed1103fa 100644 --- a/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java +++ b/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.os.Debug; import android.os.Handler; import android.os.Looper; +import android.os.RemoteException; import android.os.ResultReceiver; import android.util.Log; import android.view.InputChannel; @@ -38,8 +39,8 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import com.android.internal.annotations.GuardedBy; -import com.android.internal.inputmethod.IMultiClientInputMethodSession; import com.android.internal.inputmethod.CancellationGroup; +import com.android.internal.inputmethod.IMultiClientInputMethodSession; import com.android.internal.os.SomeArgs; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.view.IInputContext; @@ -303,6 +304,12 @@ final class MultiClientInputMethodClientCallbackAdaptor { // no-op for multi-session reportNotSupported(); } + + @Override + public void finishInput() throws RemoteException { + // no-op for multi-session + reportNotSupported(); + } } private static final class MultiClientInputMethodSessionImpl diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 44ebff99f3e9..0676ad4e2322 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -40,6 +40,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.time.Duration; import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; @@ -174,6 +175,14 @@ public abstract class NetworkAgent { public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; /** + * Sent by the NetworkAgent to ConnectivityService to pass the current + * list of underlying networks. + * obj = array of Network objects + * @hide + */ + public static final int EVENT_UNDERLYING_NETWORKS_CHANGED = BASE + 5; + + /** * Sent by ConnectivityService to the NetworkAgent to inform the agent of the * networks status - whether we could use the network or could not, due to * either a bad network configuration (no internet link) or captive portal. @@ -217,7 +226,13 @@ public abstract class NetworkAgent { * The key for the redirect URL in the Bundle argument of {@code CMD_REPORT_NETWORK_STATUS}. * @hide */ - public static String REDIRECT_URL_KEY = "redirect URL"; + public static final String REDIRECT_URL_KEY = "redirect URL"; + + /** + * Bundle key for the underlying networks in {@code EVENT_UNDERLYING_NETWORKS_CHANGED}. + * @hide + */ + public static final String UNDERLYING_NETWORKS_KEY = "underlyingNetworks"; /** * Sent by the NetworkAgent to ConnectivityService to indicate this network was @@ -650,6 +665,33 @@ public abstract class NetworkAgent { } /** + * Must be called by the agent when the network's underlying networks change. + * + * <p>{@code networks} is one of the following: + * <ul> + * <li><strong>a non-empty array</strong>: an array of one or more {@link Network}s, in + * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) + * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear + * first in the array.</li> + * <li><strong>an empty array</strong>: a zero-element array, meaning that the VPN has no + * underlying network connection, and thus, app traffic will not be sent or received.</li> + * <li><strong>null</strong>: (default) signifies that the VPN uses whatever is the system's + * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} + * APIs mentioned above to send traffic over specific channels.</li> + * </ul> + * + * @param underlyingNetworks the new list of underlying networks. + * @see {@link VpnService.Builder#setUnderlyingNetworks(Network[])} + */ + public final void setUnderlyingNetworks(@Nullable List<Network> underlyingNetworks) { + final ArrayList<Network> underlyingArray = (underlyingNetworks != null) + ? new ArrayList<>(underlyingNetworks) : null; + final Bundle bundle = new Bundle(); + bundle.putParcelableArrayList(UNDERLYING_NETWORKS_KEY, underlyingArray); + queueOrSendMessage(EVENT_UNDERLYING_NETWORKS_CHANGED, bundle); + } + + /** * Inform ConnectivityService that this agent has now connected. * Call {@link #unregister} to disconnect. */ diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 40bb8bf11d0b..8dad11ffa731 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -712,6 +712,7 @@ public final class NetworkCapabilities implements Parcelable { if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) { setAdministratorUids(new int[] {creatorUid}); } + // There is no need to clear the UIDs, they have already been cleared by clearAll() above. } /** @@ -805,7 +806,9 @@ public final class NetworkCapabilities implements Parcelable { */ private static final int TEST_NETWORKS_ALLOWED_TRANSPORTS = 1 << TRANSPORT_TEST // Test ethernet networks can be created with EthernetManager#setIncludeTestInterfaces - | 1 << TRANSPORT_ETHERNET; + | 1 << TRANSPORT_ETHERNET + // Test VPN networks can be created but their UID ranges must be empty. + | 1 << TRANSPORT_VPN; /** * Adds the given transport type to this {@code NetworkCapability} instance. diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java index d31218d9b67b..a17a49897d39 100644 --- a/core/java/android/net/NetworkProvider.java +++ b/core/java/android/net/NetworkProvider.java @@ -51,13 +51,6 @@ public class NetworkProvider { public static final int ID_NONE = -1; /** - * A hardcoded ID for NetworkAgents representing VPNs. These agents are not created by any - * provider, so they use this constant for clarity instead of NONE. - * @hide only used by ConnectivityService. - */ - public static final int ID_VPN = -2; - - /** * The first providerId value that will be allocated. * @hide only used by ConnectivityService. */ diff --git a/core/java/android/os/ParcelableHolder.java b/core/java/android/os/ParcelableHolder.java index 95c07b6b2451..fb9fa109bfa3 100644 --- a/core/java/android/os/ParcelableHolder.java +++ b/core/java/android/os/ParcelableHolder.java @@ -170,16 +170,21 @@ public final class ParcelableHolder implements Parcelable { mParcelable = null; + int dataSize = parcel.readInt(); + if (dataSize < 0) { + throw new IllegalArgumentException("dataSize from parcel is negative"); + } else if (dataSize == 0) { + if (mParcel != null) { + mParcel.recycle(); + mParcel = null; + } + return; + } if (mParcel == null) { mParcel = Parcel.obtain(); } mParcel.setDataPosition(0); mParcel.setDataSize(0); - - int dataSize = parcel.readInt(); - if (dataSize < 0) { - throw new IllegalArgumentException("dataSize from parcel is negative"); - } int dataStartPos = parcel.dataPosition(); mParcel.appendFrom(parcel, dataStartPos, dataSize); @@ -196,6 +201,11 @@ public final class ParcelableHolder implements Parcelable { return; } + if (mParcelable == null) { + parcel.writeInt(0); + return; + } + int sizePos = parcel.dataPosition(); parcel.writeInt(0); int dataStartPos = parcel.dataPosition(); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 053353330e4e..1a6eea554cae 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -648,24 +648,24 @@ interface IWindowManager void setShouldShowSystemDecors(int displayId, boolean shouldShow); /** - * Indicates that the display should show IME. + * Indicates the policy for how the display should show IME. * * @param displayId The id of the display. - * @return {@code true} if the display should show IME. + * @return The policy for how the display should show IME. * @see KeyguardManager#isDeviceSecure() * @see KeyguardManager#isDeviceLocked() */ - boolean shouldShowIme(int displayId); + int getDisplayImePolicy(int displayId); /** - * Sets that the display should show IME. + * Sets the policy for how the display should show IME. * * @param displayId The id of the display. - * @param shouldShow Indicates that the display should show IME. + * @param imePolicy Indicates the policy for how the display should show IME. * @see KeyguardManager#isDeviceSecure() * @see KeyguardManager#isDeviceLocked() */ - void setShouldShowIme(int displayId, boolean shouldShow); + void setDisplayImePolicy(int displayId, int imePolicy); /** * Waits for transactions to get applied before injecting input, optionally waiting for diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java index efc0bd2785f4..4a5c95f43d46 100644 --- a/core/java/android/view/ImeFocusController.java +++ b/core/java/android/view/ImeFocusController.java @@ -222,6 +222,25 @@ public final class ImeFocusController { } /** + * To handle the lifecycle of the input connection when the device interactivity state changed. + * (i.e. Calling IMS#onFinishInput when the device screen-off and Calling IMS#onStartInput + * when the device screen-on again). + */ + @UiThread + public void onInteractiveChanged(boolean interactive) { + final InputMethodManagerDelegate immDelegate = getImmDelegate(); + if (!immDelegate.isCurrentRootView(mViewRootImpl)) { + return; + } + if (interactive) { + final View focusedView = mViewRootImpl.mView.findFocus(); + onViewFocusChanged(focusedView, focusedView != null); + } else { + mDelegate.finishInputAndReportToIme(); + } + } + + /** * @param windowAttribute {@link WindowManager.LayoutParams} to be checked. * @return Whether the window is in local focus mode or not. */ @@ -256,6 +275,7 @@ public final class ImeFocusController { @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus); void finishInput(); + void finishInputAndReportToIme(); void closeCurrentIme(); void finishComposingText(); void setCurrentRootView(ViewRootImpl rootView); diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 22ac4dcd2cfe..8da833a28efa 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -29,6 +29,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Vibrator; +import com.android.internal.annotations.VisibleForTesting; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -423,9 +425,13 @@ public final class InputDevice implements Parcelable { } }; - // Called by native code. + /** + * Called by native code + * @hide + */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId, + @VisibleForTesting + public InputDevice(int id, int generation, int controllerNumber, String name, int vendorId, int productId, String descriptor, boolean isExternal, int sources, int keyboardType, KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone, boolean hasButtonUnderPad) { diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 607888c81357..15adc5a0ec2f 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -239,7 +239,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private static boolean useBlastAdapter(Context context) { ContentResolver contentResolver = context.getContentResolver(); return Settings.Global.getInt(contentResolver, - Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV, 1 /* default */) == 1; + Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV, 0 /* default */) == 1; } private final boolean mUseBlastAdapter; diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 436acef17c4d..ef2153e074e7 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -461,6 +461,40 @@ public interface WindowManager extends ViewManager { @interface RemoveContentMode {} /** + * Display IME Policy: The IME should appear on the local display. + * @hide + */ + @TestApi + int DISPLAY_IME_POLICY_LOCAL = 0; + + /** + * Display IME Policy: The IME should appear on the fallback display. + * @hide + */ + @TestApi + int DISPLAY_IME_POLICY_FALLBACK_DISPLAY = 1; + + /** + * Display IME Policy: The IME should be hidden. + * + * Setting this policy will prevent the IME from making a connection. This + * will prevent any IME from receiving metadata about input. + * @hide + */ + @TestApi + int DISPLAY_IME_POLICY_HIDE = 2; + + /** + * @hide + */ + @IntDef({ + DISPLAY_IME_POLICY_LOCAL, + DISPLAY_IME_POLICY_FALLBACK_DISPLAY, + DISPLAY_IME_POLICY_HIDE, + }) + @interface DisplayImePolicy {} + + /** * Exception that is thrown when trying to add view whose * {@link LayoutParams} {@link LayoutParams#token} * is invalid. @@ -695,27 +729,26 @@ public interface WindowManager extends ViewManager { } /** - * Sets that the display should show IME. + * Sets the policy for how the display should show IME. * * @param displayId Display ID. - * @param shouldShow Indicates that the display should show IME. + * @param imePolicy Indicates the policy for how the display should show IME. * @hide */ @TestApi - default void setShouldShowIme(int displayId, boolean shouldShow) { + default void setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy) { } /** - * Indicates that the display should show IME. + * Indicates the policy for how the display should show IME. * * @param displayId The id of the display. - * @return {@code true} if the display should show IME when an input field becomes - * focused on it. + * @return The policy for how the display should show IME. * @hide */ @TestApi - default boolean shouldShowIme(int displayId) { - return false; + default @DisplayImePolicy int getDisplayImePolicy(int displayId) { + return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; } public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable { @@ -2124,15 +2157,6 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY = 0x00100000; /** - * Flag to indicate that this window should be considered a screen decoration similar to the - * nav bar and status bar. This will cause this window to affect the window insets reported - * to other windows when it is visible. - * @hide - */ - @RequiresPermission(permission.STATUS_BAR_SERVICE) - public static final int PRIVATE_FLAG_IS_SCREEN_DECOR = 0x00400000; - - /** * Flag to indicate that the status bar window is in a state such that it forces showing * the navigation bar unless the navigation bar window is explicitly set to * {@link View#GONE}. @@ -2237,7 +2261,6 @@ public interface WindowManager extends ViewManager { PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE, SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, - PRIVATE_FLAG_IS_SCREEN_DECOR, PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC, PRIVATE_FLAG_USE_BLAST, @@ -2325,10 +2348,6 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, name = "IS_ROUNDED_CORNERS_OVERLAY"), @ViewDebug.FlagToString( - mask = PRIVATE_FLAG_IS_SCREEN_DECOR, - equals = PRIVATE_FLAG_IS_SCREEN_DECOR, - name = "IS_SCREEN_DECOR"), - @ViewDebug.FlagToString( mask = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, equals = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, name = "STATUS_FORCE_SHOW_NAVIGATION"), @@ -2826,7 +2845,6 @@ public interface WindowManager extends ViewManager { /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef( - flag = true, value = {LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT, LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER, diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index d56929e06906..3384bbe4fd76 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -201,20 +201,20 @@ public final class WindowManagerImpl implements WindowManager { } @Override - public void setShouldShowIme(int displayId, boolean shouldShow) { + public void setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy) { try { - WindowManagerGlobal.getWindowManagerService().setShouldShowIme(displayId, shouldShow); + WindowManagerGlobal.getWindowManagerService().setDisplayImePolicy(displayId, imePolicy); } catch (RemoteException e) { } } @Override - public boolean shouldShowIme(int displayId) { + public @DisplayImePolicy int getDisplayImePolicy(int displayId) { try { - return WindowManagerGlobal.getWindowManagerService().shouldShowIme(displayId); + return WindowManagerGlobal.getWindowManagerService().getDisplayImePolicy(displayId); } catch (RemoteException e) { } - return false; + return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; } @Override diff --git a/core/proto/android/stats/enums.proto b/core/java/android/view/inputmethod/DumpableInputConnection.java index 8f8055ed2451..9819a5734491 100644 --- a/core/proto/android/stats/enums.proto +++ b/core/java/android/view/inputmethod/DumpableInputConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,19 @@ * limitations under the License. */ -syntax = "proto2"; +package android.view.inputmethod; -package android.stats; -option java_outer_classname = "StatsEnums"; +import android.annotation.NonNull; +import android.util.proto.ProtoOutputStream; -enum EventType { - // Unknown. - TYPE_UNKNOWN = 0; - CONTENT_SUGGESTIONS_CLASSIFY_CONTENT_CALL_SUCCEEDED = 1; - CONTENT_SUGGESTIONS_CLASSIFY_CONTENT_CALL_FAILED = 2; - CONTENT_SUGGESTIONS_SUGGEST_CONTENT_CALL_SUCCEEDED = 3; - CONTENT_SUGGESTIONS_SUGGEST_CONTENT_CALL_FAILED = 4; +/** @hide */ +public interface DumpableInputConnection { + + /** + * Method used to dump state of InputConnection implementations of interest. + * + * @param proto Stream to write the state to + * @param fieldId FieldId of DumpableInputConnection as defined in the parent message + */ + void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId); } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 3c89a4bfad59..c3d3985b5ac3 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -22,6 +22,7 @@ import static android.util.imetracing.ImeTracing.PROTO_ARG; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.DISPLAY_ID; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.EDITOR_INFO; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_INSETS_SOURCE_CONSUMER; +import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INPUT_CONNECTION; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INPUT_METHOD_MANAGER; import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.VIEW_ROOT_IMPL; import static android.view.inputmethod.InputMethodManagerProto.ACTIVE; @@ -599,6 +600,27 @@ public final class InputMethodManager { } /** + * Used by {@link ImeFocusController} to finish input connection and callback + * {@link InputMethodService#onFinishInput()}. + * + * This method is especially for when ImeFocusController received device screen-off event to + * ensure the entire finish input connection and the connection lifecycle callback to + * IME can be done for security concern. + */ + @Override + public void finishInputAndReportToIme() { + synchronized (mH) { + finishInputLocked(); + if (mCurMethod != null) { + try { + mCurMethod.finishInput(); + } catch (RemoteException e) { + } + } + } + } + + /** * Used by {@link ImeFocusController} to hide current input method editor. */ @Override @@ -849,12 +871,23 @@ public final class InputMethodManager { case MSG_SET_ACTIVE: { final boolean active = msg.arg1 != 0; final boolean fullscreen = msg.arg2 != 0; + final boolean reportToImeController = msg.obj != null && (boolean) msg.obj; if (DEBUG) { Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive); } synchronized (mH) { mActive = active; mFullscreenMode = fullscreen; + + // Report active state to ImeFocusController to handle IME input + // connection lifecycle callback when it allowed. + final ImeFocusController controller = getFocusController(); + final View rootView = mCurRootView != null ? mCurRootView.getView() : null; + if (controller != null && rootView != null && reportToImeController) { + rootView.post(() -> controller.onInteractiveChanged(active)); + return; + } + if (!active) { // Some other client has starting using the IME, so note // that this happened and make sure our own editor's @@ -966,9 +999,9 @@ public final class InputMethodManager { private final InputMethodManager mParentInputMethodManager; private final WeakReference<View> mServedView; - ControlledInputConnectionWrapper(Looper mainLooper, InputConnection conn, + ControlledInputConnectionWrapper(Looper icLooper, InputConnection conn, InputMethodManager inputMethodManager, View servedView) { - super(mainLooper, conn); + super(icLooper, conn); mParentInputMethodManager = inputMethodManager; mServedView = new WeakReference<>(servedView); } @@ -1014,6 +1047,18 @@ public final class InputMethodManager { + " mServedView=" + mServedView.get() + "}"; } + + void dumpDebug(ProtoOutputStream proto, long fieldId) { + // Check that the call is initiated in the main thread of the current InputConnection + // {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are + // executed on this thread. Otherwise the messages are dispatched to the correct thread + // in IInputConnectionWrapper, but this is not wanted while dumpng, for performance + // reasons. + if (getInputConnection() instanceof DumpableInputConnection && Looper.myLooper() + == getLooper()) { + ((DumpableInputConnection) getInputConnection()).dumpDebug(proto, fieldId); + } + } } private static class ImeThreadFactory implements ThreadFactory { @@ -1061,8 +1106,9 @@ public final class InputMethodManager { } @Override - public void setActive(boolean active, boolean fullscreen) { - mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, fullscreen ? 1 : 0).sendToTarget(); + public void setActive(boolean active, boolean fullscreen, boolean reportToImeController) { + mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, fullscreen ? 1 : 0, + reportToImeController).sendToTarget(); } @Override @@ -2174,6 +2220,7 @@ public final class InputMethodManager { * @hide */ public void notifyImeHidden(IBinder windowToken) { + ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this); synchronized (mH) { try { if (mCurMethod != null && mCurRootView != null @@ -3279,6 +3326,9 @@ public final class InputMethodManager { if (mImeInsetsConsumer != null) { mImeInsetsConsumer.dumpDebug(proto, IME_INSETS_SOURCE_CONSUMER); } + if (mServedInputConnectionWrapper != null) { + mServedInputConnectionWrapper.dumpDebug(proto, INPUT_CONNECTION); + } } } } diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index a034a7c2dc7e..e08ccfddc4c5 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -156,8 +156,7 @@ public final class SelectionActionModeHelper { mSmartSelectSprite != null ? this::startSelectionActionModeWithSmartSelectAnimation : this::startSelectionActionMode, - mTextClassificationHelper::getOriginalSelection, - mTextClassificationHelper::isTextClassifierDestroyed) + mTextClassificationHelper::getOriginalSelection) .execute(); } } @@ -179,8 +178,7 @@ public final class SelectionActionModeHelper { mTextClassificationHelper.getTimeoutDuration(), mTextClassificationHelper::classifyText, this::startLinkActionMode, - mTextClassificationHelper::getOriginalSelection, - mTextClassificationHelper::isTextClassifierDestroyed) + mTextClassificationHelper::getOriginalSelection) .execute(); } } @@ -196,8 +194,7 @@ public final class SelectionActionModeHelper { mTextClassificationHelper.getTimeoutDuration(), mTextClassificationHelper::classifyText, this::invalidateActionMode, - mTextClassificationHelper::getOriginalSelection, - mTextClassificationHelper::isTextClassifierDestroyed) + mTextClassificationHelper::getOriginalSelection) .execute(); } } @@ -995,7 +992,6 @@ public final class SelectionActionModeHelper { private final Supplier<SelectionResult> mSelectionResultSupplier; private final Consumer<SelectionResult> mSelectionResultCallback; private final Supplier<SelectionResult> mTimeOutResultSupplier; - private final Supplier<Boolean> mIsTextClassifierDestroyedSupplier; private final TextView mTextView; private final String mOriginalText; @@ -1010,16 +1006,13 @@ public final class SelectionActionModeHelper { @NonNull TextView textView, int timeOut, @NonNull Supplier<SelectionResult> selectionResultSupplier, @NonNull Consumer<SelectionResult> selectionResultCallback, - @NonNull Supplier<SelectionResult> timeOutResultSupplier, - @NonNull Supplier<Boolean> isTextClassifierDestroyedSupplier) { + @NonNull Supplier<SelectionResult> timeOutResultSupplier) { super(textView != null ? textView.getHandler() : null); mTextView = Objects.requireNonNull(textView); mTimeOutDuration = timeOut; mSelectionResultSupplier = Objects.requireNonNull(selectionResultSupplier); mSelectionResultCallback = Objects.requireNonNull(selectionResultCallback); mTimeOutResultSupplier = Objects.requireNonNull(timeOutResultSupplier); - mIsTextClassifierDestroyedSupplier = - Objects.requireNonNull(isTextClassifierDestroyedSupplier); // Make a copy of the original text. mOriginalText = getText(mTextView).toString(); } @@ -1033,14 +1026,8 @@ public final class SelectionActionModeHelper { try { result = mSelectionResultSupplier.get(); } catch (IllegalStateException e) { - // Swallows the exception if the text classifier session is destroyed - if (mIsTextClassifierDestroyedSupplier.get()) { - Log.w(LOG_TAG, - "TextClassificationAsyncTask failed because TextClassifier destroyed", - e); - } else { - throw e; - } + // TODO(b/174300371): Only swallows the exception if the TCSession is destroyed + Log.w(LOG_TAG, "TextClassificationAsyncTask failed.", e); } mTextView.removeCallbacks(onTimeOut); return result; @@ -1173,10 +1160,6 @@ public final class SelectionActionModeHelper { } } - public boolean isTextClassifierDestroyed() { - return mTextClassifier.get().isDestroyed(); - } - private boolean isDarkLaunchEnabled() { return TextClassificationManager.getSettings(mContext).isModelDarkLaunchEnabled(); } diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index 0eef84765890..b4e7d6a9269f 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -19,6 +19,7 @@ package android.window; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.graphics.Point; import android.graphics.Rect; import android.os.Parcel; import android.os.Parcelable; @@ -66,6 +67,9 @@ public final class TransitionInfo implements Parcelable { private final @WindowManager.TransitionOldType int mType; private final ArrayList<Change> mChanges = new ArrayList<>(); + private SurfaceControl mRootLeash; + private final Point mRootOffset = new Point(); + /** @hide */ public TransitionInfo(@WindowManager.TransitionOldType int type) { mType = type; @@ -74,6 +78,9 @@ public final class TransitionInfo implements Parcelable { private TransitionInfo(Parcel in) { mType = in.readInt(); in.readList(mChanges, null /* classLoader */); + mRootLeash = new SurfaceControl(); + mRootLeash.readFromParcel(in); + mRootOffset.readFromParcel(in); } @Override @@ -81,6 +88,8 @@ public final class TransitionInfo implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mType); dest.writeList(mChanges); + mRootLeash.writeToParcel(dest, flags); + mRootOffset.writeToParcel(dest, flags); } @NonNull @@ -103,10 +112,35 @@ public final class TransitionInfo implements Parcelable { return 0; } + /** @see #getRootLeash() */ + public void setRootLeash(@NonNull SurfaceControl leash, int offsetLeft, int offsetTop) { + mRootLeash = leash; + mRootOffset.set(offsetLeft, offsetTop); + } + public int getType() { return mType; } + /** + * @return a surfacecontrol that can serve as a parent surfacecontrol for all the changing + * participants to animate within. This will generally be placed at the highest-z-order + * shared ancestor of all participants. + */ + @NonNull + public SurfaceControl getRootLeash() { + if (mRootLeash == null) { + throw new IllegalStateException("Trying to get a leash which wasn't set"); + } + return mRootLeash; + } + + /** @return the offset (relative to the screen) of the root leash. */ + @NonNull + public Point getRootOffset() { + return mRootOffset; + } + @NonNull public List<Change> getChanges() { return mChanges; @@ -136,7 +170,7 @@ public final class TransitionInfo implements Parcelable { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("{t=" + mType + " c=["); + sb.append("{t=" + mType + " ro=" + mRootOffset + " c=["); for (int i = 0; i < mChanges.size(); ++i) { if (i > 0) { sb.append(','); @@ -167,8 +201,9 @@ public final class TransitionInfo implements Parcelable { private WindowContainerToken mParent; private final SurfaceControl mLeash; private int mMode = TRANSIT_NONE; - private final Rect mStartBounds = new Rect(); - private final Rect mEndBounds = new Rect(); + private final Rect mStartAbsBounds = new Rect(); + private final Rect mEndAbsBounds = new Rect(); + private final Point mEndRelOffset = new Point(); public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) { mContainer = container; @@ -181,8 +216,9 @@ public final class TransitionInfo implements Parcelable { mLeash = new SurfaceControl(); mLeash.readFromParcel(in); mMode = in.readInt(); - mStartBounds.readFromParcel(in); - mEndBounds.readFromParcel(in); + mStartAbsBounds.readFromParcel(in); + mEndAbsBounds.readFromParcel(in); + mEndRelOffset.readFromParcel(in); } /** Sets the parent of this change's container. The parent must be a participant or null. */ @@ -195,14 +231,19 @@ public final class TransitionInfo implements Parcelable { mMode = mode; } - /** Sets the bounds this container occupied before the change */ - public void setStartBounds(@Nullable Rect rect) { - mStartBounds.set(rect); + /** Sets the bounds this container occupied before the change in screen space */ + public void setStartAbsBounds(@Nullable Rect rect) { + mStartAbsBounds.set(rect); } - /** Sets the bounds this container will occupy after the change */ - public void setEndBounds(@Nullable Rect rect) { - mEndBounds.set(rect); + /** Sets the bounds this container will occupy after the change in screen space */ + public void setEndAbsBounds(@Nullable Rect rect) { + mEndAbsBounds.set(rect); + } + + /** Sets the offset of this container from its parent surface */ + public void setEndRelOffset(int left, int top) { + mEndRelOffset.set(left, top); } /** @return the container that is changing. May be null if non-remotable (eg. activity) */ @@ -230,8 +271,8 @@ public final class TransitionInfo implements Parcelable { * is coming into existence. */ @NonNull - public Rect getStartBounds() { - return mStartBounds; + public Rect getStartAbsBounds() { + return mStartAbsBounds; } /** @@ -239,8 +280,16 @@ public final class TransitionInfo implements Parcelable { * is disappearing. */ @NonNull - public Rect getEndBounds() { - return mEndBounds; + public Rect getEndAbsBounds() { + return mEndAbsBounds; + } + + /** + * @return the offset of the container's surface from its parent surface after the change. + */ + @NonNull + public Point getEndRelOffset() { + return mEndRelOffset; } /** @return the leash or surface to animate for this container */ @@ -256,8 +305,9 @@ public final class TransitionInfo implements Parcelable { dest.writeTypedObject(mParent, flags); mLeash.writeToParcel(dest, flags); dest.writeInt(mMode); - mStartBounds.writeToParcel(dest, flags); - mEndBounds.writeToParcel(dest, flags); + mStartAbsBounds.writeToParcel(dest, flags); + mEndAbsBounds.writeToParcel(dest, flags); + mEndRelOffset.writeToParcel(dest, flags); } @NonNull @@ -283,8 +333,8 @@ public final class TransitionInfo implements Parcelable { @Override public String toString() { return "{" + mContainer + "(" + mParent + ") leash=" + mLeash - + " m=" + modeToString(mMode) + " sb=" + mStartBounds - + " eb=" + mEndBounds + "}"; + + " m=" + modeToString(mMode) + " sb=" + mStartAbsBounds + + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + "}"; } } } diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java index 7a87be35ea98..b9d3df678a91 100644 --- a/core/java/com/android/internal/compat/ChangeReporter.java +++ b/core/java/com/android/internal/compat/ChangeReporter.java @@ -223,7 +223,7 @@ public final class ChangeReporter { FrameworkStatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__SOURCE__SYSTEM_SERVER; @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, prefix = { "STATE_" }, value = { + @IntDef(prefix = { "STATE_" }, value = { STATE_UNKNOWN_STATE, STATE_ENABLED, STATE_DISABLED, @@ -233,7 +233,7 @@ public final class ChangeReporter { } @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, prefix = { "SOURCE_" }, value = { + @IntDef(prefix = { "SOURCE_" }, value = { SOURCE_UNKNOWN_SOURCE, SOURCE_APP_PROCESS, SOURCE_SYSTEM_SERVER diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 1fcc6b0a6d55..94e21e5a5965 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -391,16 +391,19 @@ public class ZygoteInit { SharedLibraryInfo hidlBase = new SharedLibraryInfo( "/system/framework/android.hidl.base-V1.0-java.jar", null /*packageName*/, null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN, - null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/); + null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/, + false /*isNative*/); SharedLibraryInfo hidlManager = new SharedLibraryInfo( "/system/framework/android.hidl.manager-V1.0-java.jar", null /*packageName*/, null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN, - null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/); + null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/, + false /*isNative*/); SharedLibraryInfo androidTestBase = new SharedLibraryInfo( "/system/framework/android.test.base.jar", null /*packageName*/, null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN, - null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/); + null /*declaringPackage*/, null /*dependentPackages*/, null /*dependencies*/, + false /*isNative*/); ApplicationLoaders.getDefault().createAndCacheNonBootclasspathSystemClassLoaders( new SharedLibraryInfo[]{ @@ -625,8 +628,11 @@ public class ZygoteInit { /** * Creates a PathClassLoader for the given class path that is associated with a shared - * namespace, i.e., this classloader can access platform-private native libraries. The - * classloader will use java.library.path as the native library path. + * namespace, i.e., this classloader can access platform-private native libraries. + * + * The classloader will add java.library.path to the native library path for the classloader + * namespace. Since it includes platform locations like /system/lib, this is only appropriate + * for platform code that don't need linker namespace isolation (as opposed to APEXes and apps). */ static ClassLoader createPathClassLoader(String classPath, int targetSdkVersion) { String libraryPath = System.getProperty("java.library.path"); diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java index 33ebe43cb23a..4deb40a0d772 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -25,6 +25,7 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.os.Trace; import android.util.Log; import android.view.KeyEvent; import android.view.inputmethod.CompletionInfo; @@ -111,6 +112,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { } } + protected Looper getLooper() { + synchronized (mMainLooper) { + return mMainLooper; + } + } + protected boolean isFinished() { synchronized (mLock) { return mFinished; @@ -259,61 +266,80 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { void executeMessage(Message msg) { switch (msg.what) { case DO_GET_TEXT_AFTER_CURSOR: { - final ICharSequenceResultCallback callback = (ICharSequenceResultCallback) msg.obj; - final InputConnection ic = getInputConnection(); - final CharSequence result; - if (ic == null || !isActive()) { - Log.w(TAG, "getTextAfterCursor on inactive InputConnection"); - result = null; - } else { - result = ic.getTextAfterCursor(msg.arg1, msg.arg2); - } + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextAfterCursor"); try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getTextAfterCursor()." + final ICharSequenceResultCallback callback = + (ICharSequenceResultCallback) msg.obj; + final InputConnection ic = getInputConnection(); + final CharSequence result; + if (ic == null || !isActive()) { + Log.w(TAG, "getTextAfterCursor on inactive InputConnection"); + result = null; + } else { + result = ic.getTextAfterCursor(msg.arg1, msg.arg2); + } + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getTextAfterCursor()." + " result=" + result, e); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } case DO_GET_TEXT_BEFORE_CURSOR: { - final ICharSequenceResultCallback callback = (ICharSequenceResultCallback) msg.obj; - final InputConnection ic = getInputConnection(); - final CharSequence result; - if (ic == null || !isActive()) { - Log.w(TAG, "getTextBeforeCursor on inactive InputConnection"); - result = null; - } else { - result = ic.getTextBeforeCursor(msg.arg1, msg.arg2); - } + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextBeforeCursor"); try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getTextBeforeCursor()." + final ICharSequenceResultCallback callback = + (ICharSequenceResultCallback) msg.obj; + final InputConnection ic = getInputConnection(); + final CharSequence result; + if (ic == null || !isActive()) { + Log.w(TAG, "getTextBeforeCursor on inactive InputConnection"); + result = null; + } else { + result = ic.getTextBeforeCursor(msg.arg1, msg.arg2); + } + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getTextBeforeCursor()." + " result=" + result, e); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } case DO_GET_SELECTED_TEXT: { - final ICharSequenceResultCallback callback = (ICharSequenceResultCallback) msg.obj; - final InputConnection ic = getInputConnection(); - final CharSequence result; - if (ic == null || !isActive()) { - Log.w(TAG, "getSelectedText on inactive InputConnection"); - result = null; - } else { - result = ic.getSelectedText(msg.arg1); - } + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSelectedText"); try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getSelectedText()." - + " result=" + result, e); + final ICharSequenceResultCallback callback = + (ICharSequenceResultCallback) msg.obj; + final InputConnection ic = getInputConnection(); + final CharSequence result; + if (ic == null || !isActive()) { + Log.w(TAG, "getSelectedText on inactive InputConnection"); + result = null; + } else { + result = ic.getSelectedText(msg.arg1); + } + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getSelectedText()." + + " result=" + result, e); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } case DO_GET_SURROUNDING_TEXT: { final SomeArgs args = (SomeArgs) msg.obj; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSurroundingText"); try { int beforeLength = (int) args.arg1; int afterLength = (int) args.arg2; @@ -335,30 +361,37 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { + " result=" + result, e); } } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); args.recycle(); } return; } case DO_GET_CURSOR_CAPS_MODE: { - final IIntResultCallback callback = (IIntResultCallback) msg.obj; - final InputConnection ic = getInputConnection(); - final int result; - if (ic == null || !isActive()) { - Log.w(TAG, "getCursorCapsMode on inactive InputConnection"); - result = 0; - } else { - result = ic.getCursorCapsMode(msg.arg1); - } + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getCursorCapsMode"); try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getCursorCapsMode()." + final IIntResultCallback callback = (IIntResultCallback) msg.obj; + final InputConnection ic = getInputConnection(); + final int result; + if (ic == null || !isActive()) { + Log.w(TAG, "getCursorCapsMode on inactive InputConnection"); + result = 0; + } else { + result = ic.getCursorCapsMode(msg.arg1); + } + try { + callback.onResult(result); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to getCursorCapsMode()." + " result=" + result, e); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } case DO_GET_EXTRACTED_TEXT: { final SomeArgs args = (SomeArgs) msg.obj; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getExtractedText"); try { final ExtractedTextRequest request = (ExtractedTextRequest) args.arg1; final IExtractedTextResultCallback callback = @@ -378,159 +411,237 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { + " result=" + result, e); } } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); args.recycle(); } return; } case DO_COMMIT_TEXT: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "commitText on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitText"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "commitText on inactive InputConnection"); + return; + } + ic.commitText((CharSequence) msg.obj, msg.arg1); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.commitText((CharSequence)msg.obj, msg.arg1); return; } case DO_SET_SELECTION: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "setSelection on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setSelection"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "setSelection on inactive InputConnection"); + return; + } + ic.setSelection(msg.arg1, msg.arg2); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.setSelection(msg.arg1, msg.arg2); return; } case DO_PERFORM_EDITOR_ACTION: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "performEditorAction on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performEditorAction"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "performEditorAction on inactive InputConnection"); + return; + } + ic.performEditorAction(msg.arg1); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.performEditorAction(msg.arg1); return; } case DO_PERFORM_CONTEXT_MENU_ACTION: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "performContextMenuAction on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performContextMenuAction"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "performContextMenuAction on inactive InputConnection"); + return; + } + ic.performContextMenuAction(msg.arg1); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.performContextMenuAction(msg.arg1); return; } case DO_COMMIT_COMPLETION: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "commitCompletion on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitCompletion"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "commitCompletion on inactive InputConnection"); + return; + } + ic.commitCompletion((CompletionInfo) msg.obj); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.commitCompletion((CompletionInfo)msg.obj); return; } case DO_COMMIT_CORRECTION: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "commitCorrection on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitCorrection"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "commitCorrection on inactive InputConnection"); + return; + } + ic.commitCorrection((CorrectionInfo) msg.obj); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.commitCorrection((CorrectionInfo)msg.obj); return; } case DO_SET_COMPOSING_TEXT: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "setComposingText on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setComposingText"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "setComposingText on inactive InputConnection"); + return; + } + ic.setComposingText((CharSequence) msg.obj, msg.arg1); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.setComposingText((CharSequence)msg.obj, msg.arg1); return; } case DO_SET_COMPOSING_REGION: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "setComposingRegion on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#setComposingRegion"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "setComposingRegion on inactive InputConnection"); + return; + } + ic.setComposingRegion(msg.arg1, msg.arg2); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.setComposingRegion(msg.arg1, msg.arg2); return; } case DO_FINISH_COMPOSING_TEXT: { - if (isFinished()) { - // In this case, #finishComposingText() is guaranteed to be called already. - // There should be no negative impact if we ignore this call silently. - if (DEBUG) { - Log.w(TAG, "Bug 35301295: Redundant finishComposingText."); + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#finishComposingText"); + try { + if (isFinished()) { + // In this case, #finishComposingText() is guaranteed to be called already. + // There should be no negative impact if we ignore this call silently. + if (DEBUG) { + Log.w(TAG, "Bug 35301295: Redundant finishComposingText."); + } + return; } - return; - } - InputConnection ic = getInputConnection(); - // Note we do NOT check isActive() here, because this is safe - // for an IME to call at any time, and we need to allow it - // through to clean up our state after the IME has switched to - // another client. - if (ic == null) { - Log.w(TAG, "finishComposingText on inactive InputConnection"); - return; + InputConnection ic = getInputConnection(); + // Note we do NOT check isActive() here, because this is safe + // for an IME to call at any time, and we need to allow it + // through to clean up our state after the IME has switched to + // another client. + if (ic == null) { + Log.w(TAG, "finishComposingText on inactive InputConnection"); + return; + } + ic.finishComposingText(); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.finishComposingText(); return; } case DO_SEND_KEY_EVENT: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "sendKeyEvent on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#sendKeyEvent"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "sendKeyEvent on inactive InputConnection"); + return; + } + ic.sendKeyEvent((KeyEvent) msg.obj); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.sendKeyEvent((KeyEvent)msg.obj); return; } case DO_CLEAR_META_KEY_STATES: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "clearMetaKeyStates on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#clearMetaKeyStates"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "clearMetaKeyStates on inactive InputConnection"); + return; + } + ic.clearMetaKeyStates(msg.arg1); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.clearMetaKeyStates(msg.arg1); return; } case DO_DELETE_SURROUNDING_TEXT: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "deleteSurroundingText on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#deleteSurroundingText"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "deleteSurroundingText on inactive InputConnection"); + return; + } + ic.deleteSurroundingText(msg.arg1, msg.arg2); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.deleteSurroundingText(msg.arg1, msg.arg2); return; } case DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, + "InputConnection#deleteSurroundingTextInCodePoints"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection"); + return; + } + ic.deleteSurroundingTextInCodePoints(msg.arg1, msg.arg2); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.deleteSurroundingTextInCodePoints(msg.arg1, msg.arg2); return; } case DO_BEGIN_BATCH_EDIT: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "beginBatchEdit on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#beginBatchEdit"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "beginBatchEdit on inactive InputConnection"); + return; + } + ic.beginBatchEdit(); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.beginBatchEdit(); return; } case DO_END_BATCH_EDIT: { - InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { - Log.w(TAG, "endBatchEdit on inactive InputConnection"); - return; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#endBatchEdit"); + try { + InputConnection ic = getInputConnection(); + if (ic == null || !isActive()) { + Log.w(TAG, "endBatchEdit on inactive InputConnection"); + return; + } + ic.endBatchEdit(); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } - ic.endBatchEdit(); return; } case DO_PERFORM_PRIVATE_COMMAND: { final SomeArgs args = (SomeArgs) msg.obj; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performPrivateCommand"); try { final String action = (String) args.arg1; final Bundle data = (Bundle) args.arg2; @@ -541,25 +652,31 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { } ic.performPrivateCommand(action, data); } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); args.recycle(); } return; } case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: { - final IIntResultCallback callback = (IIntResultCallback) msg.obj; - final InputConnection ic = getInputConnection(); - final boolean result; - if (ic == null || !isActive()) { - Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection"); - result = false; - } else { - result = ic.requestCursorUpdates(msg.arg1); - } + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#requestCursorUpdates"); try { - callback.onResult(result ? 1 : 0); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to requestCursorUpdates()." - + " result=" + result, e); + final IIntResultCallback callback = (IIntResultCallback) msg.obj; + final InputConnection ic = getInputConnection(); + final boolean result; + if (ic == null || !isActive()) { + Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection"); + result = false; + } else { + result = ic.requestCursorUpdates(msg.arg1); + } + try { + callback.onResult(result ? 1 : 0); + } catch (RemoteException e) { + Log.w(TAG, "Failed to return the result to requestCursorUpdates()." + + " result=" + result, e); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } @@ -571,6 +688,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { if (isFinished()) { return; } + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#closeConnection"); try { InputConnection ic = getInputConnection(); // Note we do NOT check isActive() here, because this is safe @@ -590,12 +708,14 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { mInputConnection = null; mFinished = true; } + Trace.traceEnd(Trace.TRACE_TAG_INPUT); } return; } case DO_COMMIT_CONTENT: { final int flags = msg.arg1; SomeArgs args = (SomeArgs) msg.obj; + Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitContent"); try { final IIntResultCallback callback = (IIntResultCallback) args.arg3; final InputConnection ic = getInputConnection(); @@ -620,6 +740,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { + " result=" + result, e); } } finally { + Trace.traceEnd(Trace.TRACE_TAG_INPUT); args.recycle(); } return; diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl index 1145f5183206..ec9a0a2f4801 100644 --- a/core/java/com/android/internal/view/IInputMethodClient.aidl +++ b/core/java/com/android/internal/view/IInputMethodClient.aidl @@ -25,7 +25,7 @@ import com.android.internal.view.InputBindResult; oneway interface IInputMethodClient { void onBindMethod(in InputBindResult res); void onUnbindMethod(int sequence, int unbindReason); - void setActive(boolean active, boolean fullscreen); + void setActive(boolean active, boolean fullscreen, boolean reportToImeController); void scheduleStartInputIfNecessary(boolean fullscreen); void reportFullscreenMode(boolean fullscreen); void applyImeVisibility(boolean setVisible); diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 844c56bd3529..33abbe82c109 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -79,4 +79,9 @@ interface IInputMethodManager { void removeImeSurfaceFromWindow(in IBinder windowToken); void startProtoDump(in byte[] protoDump, int source, String where); boolean isImeTraceEnabled(); + + // Starts an ime trace. + void startImeTrace(); + // Stops an ime trace. + void stopImeTrace(); } diff --git a/core/java/com/android/internal/view/IInputMethodSession.aidl b/core/java/com/android/internal/view/IInputMethodSession.aidl index 0319e3637384..c6afd78ec04b 100644 --- a/core/java/com/android/internal/view/IInputMethodSession.aidl +++ b/core/java/com/android/internal/view/IInputMethodSession.aidl @@ -52,4 +52,6 @@ oneway interface IInputMethodSession { void notifyImeHidden(); void removeImeSurface(); + + void finishInput(); } diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java index ff3543c837eb..d30d662806d4 100644 --- a/core/java/com/android/internal/widget/EditableInputConnection.java +++ b/core/java/com/android/internal/widget/EditableInputConnection.java @@ -16,21 +16,36 @@ package com.android.internal.widget; +import static android.view.inputmethod.InputConnectionProto.CURSOR_CAPS_MODE; +import static android.view.inputmethod.InputConnectionProto.EDITABLE_TEXT; +import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT; +import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT_END; +import static android.view.inputmethod.InputConnectionProto.SELECTED_TEXT_START; + import android.compat.annotation.UnsupportedAppUsage; import android.os.Bundle; import android.text.Editable; +import android.text.Selection; import android.text.method.KeyListener; import android.util.Log; +import android.util.proto.ProtoOutputStream; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; +import android.view.inputmethod.DumpableInputConnection; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.widget.TextView; -public class EditableInputConnection extends BaseInputConnection { +/** + * Base class for an editable InputConnection instance. This is created by {@link TextView} or + * {@link EditText}. + */ +public class EditableInputConnection extends BaseInputConnection + implements DumpableInputConnection { private static final boolean DEBUG = false; + private static final boolean DUMP_TEXT = false; private static final String TAG = "EditableInputConnection"; private final TextView mTextView; @@ -222,4 +237,28 @@ public class EditableInputConnection extends BaseInputConnection { } return true; } + + @Override + public void dumpDebug(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + CharSequence editableText = mTextView.getText(); + CharSequence selectedText = getSelectedText(0 /* flags */); + if (DUMP_TEXT) { + if (editableText != null) { + proto.write(EDITABLE_TEXT, editableText.toString()); + } + if (selectedText != null) { + proto.write(SELECTED_TEXT, selectedText.toString()); + } + } + final Editable content = getEditable(); + if (content != null) { + int start = Selection.getSelectionStart(content); + int end = Selection.getSelectionEnd(content); + proto.write(SELECTED_TEXT_START, start); + proto.write(SELECTED_TEXT_END, end); + } + proto.write(CURSOR_CAPS_MODE, getCursorCapsMode(0)); + proto.end(token); + } } diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 58817a8a48a9..514e0b8e0ded 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -61,12 +61,17 @@ import android.widget.PopupWindow; import android.widget.TextView; import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.util.ArrayList; +import java.util.Collection; import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Objects; /** @@ -93,7 +98,6 @@ public final class FloatingToolbar { private final Rect mPreviousContentRect = new Rect(); private Menu mMenu; - private List<MenuItem> mShowingMenuItems = new ArrayList<>(); private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER; private int mSuggestedWidth; @@ -274,10 +278,11 @@ public final class FloatingToolbar { private void doShow() { List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu); menuItems.sort(mMenuItemComparator); - if (!isCurrentlyShowing(menuItems) || mWidthChanged) { + if (mPopup.isLayoutRequired(menuItems) || mWidthChanged) { mPopup.dismiss(); mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth); - mShowingMenuItems = menuItems; + } else { + mPopup.updateMenuItems(menuItems, mMenuItemClickListener); } if (!mPopup.isShowing()) { mPopup.show(mContentRect); @@ -289,33 +294,10 @@ public final class FloatingToolbar { } /** - * Returns true if this floating toolbar is currently showing the specified menu items. - */ - private boolean isCurrentlyShowing(List<MenuItem> menuItems) { - if (mShowingMenuItems == null || menuItems.size() != mShowingMenuItems.size()) { - return false; - } - - final int size = menuItems.size(); - for (int i = 0; i < size; i++) { - final MenuItem menuItem = menuItems.get(i); - final MenuItem showingItem = mShowingMenuItems.get(i); - if (menuItem.getItemId() != showingItem.getItemId() - || !TextUtils.equals(menuItem.getTitle(), showingItem.getTitle()) - || !Objects.equals(menuItem.getIcon(), showingItem.getIcon()) - || menuItem.getGroupId() != showingItem.getGroupId()) { - return false; - } - } - - return true; - } - - /** * Returns the visible and enabled menu items in the specified menu. * This method is recursive. */ - private List<MenuItem> getVisibleAndEnabledMenuItems(Menu menu) { + private static List<MenuItem> getVisibleAndEnabledMenuItems(Menu menu) { List<MenuItem> menuItems = new ArrayList<>(); for (int i = 0; (menu != null) && (i < menu.size()); i++) { MenuItem menuItem = menu.getItem(i); @@ -427,17 +409,25 @@ public final class FloatingToolbar { private Size mOverflowPanelSize; // Should be null when there is no overflow. private Size mMainPanelSize; - /* Item click listeners */ + /* Menu items and click listeners */ + private final Map<MenuItemRepr, MenuItem> mMenuItems = new LinkedHashMap<>(); private MenuItem.OnMenuItemClickListener mOnMenuItemClickListener; private final View.OnClickListener mMenuItemButtonOnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { - if (v.getTag() instanceof MenuItem) { - if (mOnMenuItemClickListener != null) { - mOnMenuItemClickListener.onMenuItemClick((MenuItem) v.getTag()); - } + if (mOnMenuItemClickListener == null) { + return; + } + final Object tag = v.getTag(); + if (!(tag instanceof MenuItemRepr)) { + return; } + final MenuItem menuItem = mMenuItems.get((MenuItemRepr) tag); + if (menuItem == null) { + return; + } + mOnMenuItemClickListener.onMenuItemClick(menuItem); } }; @@ -558,9 +548,9 @@ public final class FloatingToolbar { List<MenuItem> menuItems, MenuItem.OnMenuItemClickListener menuItemClickListener, int suggestedWidth) { - mOnMenuItemClickListener = menuItemClickListener; cancelOverflowAnimations(); clearPanels(); + updateMenuItems(menuItems, menuItemClickListener); menuItems = layoutMainPanelItems(menuItems, getAdjustedToolbarWidth(suggestedWidth)); if (!menuItems.isEmpty()) { // Add remaining items to the overflow. @@ -570,6 +560,28 @@ public final class FloatingToolbar { } /** + * Updates the popup's menu items without rebuilding the widget. + * Use in place of layoutMenuItems() when the popup's views need not be reconstructed. + * + * @see isLayoutRequired(List<MenuItem>) + */ + public void updateMenuItems( + List<MenuItem> menuItems, MenuItem.OnMenuItemClickListener menuItemClickListener) { + mMenuItems.clear(); + for (MenuItem menuItem : menuItems) { + mMenuItems.put(MenuItemRepr.of(menuItem), menuItem); + } + mOnMenuItemClickListener = menuItemClickListener; + } + + /** + * Returns true if this popup needs a relayout to properly render the specified menu items. + */ + public boolean isLayoutRequired(List<MenuItem> menuItems) { + return !MenuItemRepr.reprEquals(menuItems, mMenuItems.values()); + } + + /** * Shows this popup at the specified coordinates. * The specified coordinates may be adjusted to make sure the popup is entirely on-screen. */ @@ -1374,7 +1386,7 @@ public final class FloatingToolbar { } private void setButtonTagAndClickListener(View menuItemButton, MenuItem menuItem) { - menuItemButton.setTag(menuItem); + menuItemButton.setTag(MenuItemRepr.of(menuItem)); menuItemButton.setOnClickListener(mMenuItemButtonOnClickListener); } @@ -1656,6 +1668,85 @@ public final class FloatingToolbar { } /** + * Represents the identity of a MenuItem that is rendered in a FloatingToolbarPopup. + */ + @VisibleForTesting + public static final class MenuItemRepr { + + public final int itemId; + public final int groupId; + @Nullable public final String title; + @Nullable private final Drawable mIcon; + + private MenuItemRepr( + int itemId, int groupId, @Nullable CharSequence title, @Nullable Drawable icon) { + this.itemId = itemId; + this.groupId = groupId; + this.title = (title == null) ? null : title.toString(); + mIcon = icon; + } + + /** + * Creates an instance of MenuItemRepr for the specified menu item. + */ + public static MenuItemRepr of(MenuItem menuItem) { + return new MenuItemRepr( + menuItem.getItemId(), + menuItem.getGroupId(), + menuItem.getTitle(), + menuItem.getIcon()); + } + + /** + * Returns this object's hashcode. + */ + @Override + public int hashCode() { + return Objects.hash(itemId, groupId, title, mIcon); + } + + /** + * Returns true if this object is the same as the specified object. + */ + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof MenuItemRepr)) { + return false; + } + final MenuItemRepr other = (MenuItemRepr) o; + return itemId == other.itemId + && groupId == other.groupId + && TextUtils.equals(title, other.title) + // Many Drawables (icons) do not implement equals(). Using equals() here instead + // of reference comparisons in case a Drawable subclass implements equals(). + && Objects.equals(mIcon, other.mIcon); + } + + /** + * Returns true if the two menu item collections are the same based on MenuItemRepr. + */ + public static boolean reprEquals( + Collection<MenuItem> menuItems1, Collection<MenuItem> menuItems2) { + if (menuItems1.size() != menuItems2.size()) { + return false; + } + + final Iterator<MenuItem> menuItems2Iter = menuItems2.iterator(); + for (MenuItem menuItem1 : menuItems1) { + final MenuItem menuItem2 = menuItems2Iter.next(); + if (!MenuItemRepr.of(menuItem1).equals(MenuItemRepr.of(menuItem2))) { + return false; + } + } + + return true; + } + } + + /** * Creates and returns a menu button for the specified menu item. */ private static View createMenuItemButton( diff --git a/core/proto/Android.bp b/core/proto/Android.bp deleted file mode 100644 index 3b891d6b4947..000000000000 --- a/core/proto/Android.bp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// C++ library for Bluetooth platform wide protobuf definitions -cc_library_static { - name: "libbt-platform-protos-lite", - host_supported: true, - proto: { - export_proto_headers: true, - type: "lite", - }, - srcs: [ - "android/bluetooth/a2dp/enums.proto", - "android/bluetooth/enums.proto", - "android/bluetooth/hci/enums.proto", - "android/bluetooth/hfp/enums.proto", - "android/bluetooth/smp/enums.proto", - ], -} diff --git a/core/proto/android/app/enums.proto b/core/proto/android/app/enums.proto deleted file mode 100644 index 722194b322c6..000000000000 --- a/core/proto/android/app/enums.proto +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.app; - -option java_outer_classname = "AppProtoEnums"; -option java_multiple_files = true; - -// ActivityManagerInternal.java's APP_TRANSITION reasons. -enum AppTransitionReasonEnum { - APP_TRANSITION_REASON_UNKNOWN = 0; - // The transition was started because we drew the splash screen. - APP_TRANSITION_SPLASH_SCREEN = 1; - // The transition was started because we all app windows were drawn. - APP_TRANSITION_WINDOWS_DRAWN = 2; - // The transition was started because of a timeout. - APP_TRANSITION_TIMEOUT = 3; - // The transition was started because of a we drew a task snapshot. - APP_TRANSITION_SNAPSHOT = 4; - // The transition was started because it was a recents animation and we only needed to wait on - // the wallpaper. - APP_TRANSITION_RECENTS_ANIM = 5; -} - -// ActivityManager.java PROCESS_STATEs -// Next tag: 1021 -enum ProcessStateEnum { - // Unlike the ActivityManager PROCESS_STATE values, the ordering and numerical values - // here are completely fixed and arbitrary. Order is irrelevant. - // No attempt need be made to keep them in sync. - // The values here must not be modified. Any new process states can be appended to the end. - - // Process state that is unknown to this proto file (i.e. is not mapped - // by ActivityManager.processStateAmToProto()). Can only happen if there's a bug in the mapping. - PROCESS_STATE_UNKNOWN_TO_PROTO = 998; - // Not a real process state. - PROCESS_STATE_UNKNOWN = 999; - // Process is a persistent system process. - PROCESS_STATE_PERSISTENT = 1000; - // Process is a persistent system process and is doing UI. - PROCESS_STATE_PERSISTENT_UI = 1001; - // Process is hosting the current top activities. Note that this covers - // all activities that are visible to the user. - PROCESS_STATE_TOP = 1002; - // Process is bound to a TOP app. - PROCESS_STATE_BOUND_TOP = 1020; - // Process is hosting a foreground service. - PROCESS_STATE_FOREGROUND_SERVICE = 1003; - // Process is hosting a service bound by the system or another foreground app. - PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 1004; - // Process is important to the user, and something they are aware of. - PROCESS_STATE_IMPORTANT_FOREGROUND = 1005; - // Process is important to the user, but not something they are aware of. - PROCESS_STATE_IMPORTANT_BACKGROUND = 1006; - // Process is in the background transient so we will try to keep running. - PROCESS_STATE_TRANSIENT_BACKGROUND = 1007; - // Process is in the background running a backup/restore operation. - PROCESS_STATE_BACKUP = 1008; - // Process is in the background running a service. Unlike oom_adj, this - // level is used for both the normal running in background state and the - // executing operations state. - PROCESS_STATE_SERVICE = 1009; - // Process is in the background running a receiver. Note that from the - // perspective of oom_adj, receivers run at a higher foreground level, but - // for our prioritization here that is not necessary and putting them - // below services means many fewer changes in some process states as they - // receive broadcasts. - PROCESS_STATE_RECEIVER = 1010; - // Same as PROCESS_STATE_TOP but while device is sleeping. - PROCESS_STATE_TOP_SLEEPING = 1011; - // Process is in the background, but it can't restore its state so we want - // to try to avoid killing it. - PROCESS_STATE_HEAVY_WEIGHT = 1012; - // Process is in the background but hosts the home activity. - PROCESS_STATE_HOME = 1013; - // Process is in the background but hosts the last shown activity. - PROCESS_STATE_LAST_ACTIVITY = 1014; - // Process is being cached for later use and contains activities. - PROCESS_STATE_CACHED_ACTIVITY = 1015; - // Process is being cached for later use and is a client of another cached - // process that contains activities. - PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 1016; - // Process is being cached for later use and has an activity that corresponds - // to an existing recent task. - PROCESS_STATE_CACHED_RECENT = 1017; - // Process is being cached for later use and is empty. - PROCESS_STATE_CACHED_EMPTY = 1018; - // Process does not exist. - PROCESS_STATE_NONEXISTENT = 1019; -} - -// AppOpsManager.java - operation ids for logging -enum AppOpEnum { - APP_OP_NONE = -1; - APP_OP_COARSE_LOCATION = 0; - APP_OP_FINE_LOCATION = 1; - APP_OP_GPS = 2; - APP_OP_VIBRATE = 3; - APP_OP_READ_CONTACTS = 4; - APP_OP_WRITE_CONTACTS = 5; - APP_OP_READ_CALL_LOG = 6; - APP_OP_WRITE_CALL_LOG = 7; - APP_OP_READ_CALENDAR = 8; - APP_OP_WRITE_CALENDAR = 9; - APP_OP_WIFI_SCAN = 10; - APP_OP_POST_NOTIFICATION = 11; - APP_OP_NEIGHBORING_CELLS = 12; - APP_OP_CALL_PHONE = 13; - APP_OP_READ_SMS = 14; - APP_OP_WRITE_SMS = 15; - APP_OP_RECEIVE_SMS = 16; - APP_OP_RECEIVE_EMERGENCY_SMS = 17; - APP_OP_RECEIVE_MMS = 18; - APP_OP_RECEIVE_WAP_PUSH = 19; - APP_OP_SEND_SMS = 20; - APP_OP_READ_ICC_SMS = 21; - APP_OP_WRITE_ICC_SMS = 22; - APP_OP_WRITE_SETTINGS = 23; - APP_OP_SYSTEM_ALERT_WINDOW = 24; - APP_OP_ACCESS_NOTIFICATIONS = 25; - APP_OP_CAMERA = 26; - APP_OP_RECORD_AUDIO = 27; - APP_OP_PLAY_AUDIO = 28; - APP_OP_READ_CLIPBOARD = 29; - APP_OP_WRITE_CLIPBOARD = 30; - APP_OP_TAKE_MEDIA_BUTTONS = 31; - APP_OP_TAKE_AUDIO_FOCUS = 32; - APP_OP_AUDIO_MASTER_VOLUME = 33; - APP_OP_AUDIO_VOICE_VOLUME = 34; - APP_OP_AUDIO_RING_VOLUME = 35; - APP_OP_AUDIO_MEDIA_VOLUME = 36; - APP_OP_AUDIO_ALARM_VOLUME = 37; - APP_OP_AUDIO_NOTIFICATION_VOLUME = 38; - APP_OP_AUDIO_BLUETOOTH_VOLUME = 39; - APP_OP_WAKE_LOCK = 40; - APP_OP_MONITOR_LOCATION = 41; - APP_OP_MONITOR_HIGH_POWER_LOCATION = 42; - APP_OP_GET_USAGE_STATS = 43; - APP_OP_MUTE_MICROPHONE = 44; - APP_OP_TOAST_WINDOW = 45; - APP_OP_PROJECT_MEDIA = 46; - APP_OP_ACTIVATE_VPN = 47; - APP_OP_WRITE_WALLPAPER = 48; - APP_OP_ASSIST_STRUCTURE = 49; - APP_OP_ASSIST_SCREENSHOT = 50; - APP_OP_READ_PHONE_STATE = 51; - APP_OP_ADD_VOICEMAIL = 52; - APP_OP_USE_SIP = 53; - APP_OP_PROCESS_OUTGOING_CALLS = 54; - APP_OP_USE_FINGERPRINT = 55; - APP_OP_BODY_SENSORS = 56; - APP_OP_READ_CELL_BROADCASTS = 57; - APP_OP_MOCK_LOCATION = 58; - APP_OP_READ_EXTERNAL_STORAGE = 59; - APP_OP_WRITE_EXTERNAL_STORAGE = 60; - APP_OP_TURN_SCREEN_ON = 61; - APP_OP_GET_ACCOUNTS = 62; - APP_OP_RUN_IN_BACKGROUND = 63; - APP_OP_AUDIO_ACCESSIBILITY_VOLUME = 64; - APP_OP_READ_PHONE_NUMBERS = 65; - APP_OP_REQUEST_INSTALL_PACKAGES = 66; - APP_OP_PICTURE_IN_PICTURE = 67; - APP_OP_INSTANT_APP_START_FOREGROUND = 68; - APP_OP_ANSWER_PHONE_CALLS = 69; - APP_OP_RUN_ANY_IN_BACKGROUND = 70; - APP_OP_CHANGE_WIFI_STATE = 71; - APP_OP_REQUEST_DELETE_PACKAGES = 72; - APP_OP_BIND_ACCESSIBILITY_SERVICE = 73; - APP_OP_ACCEPT_HANDOVER = 74; - APP_OP_MANAGE_IPSEC_TUNNELS = 75; - APP_OP_START_FOREGROUND = 76; - APP_OP_BLUETOOTH_SCAN = 77; - APP_OP_USE_BIOMETRIC = 78; - APP_OP_ACTIVITY_RECOGNITION = 79; - APP_OP_SMS_FINANCIAL_TRANSACTIONS = 80; - APP_OP_READ_MEDIA_AUDIO = 81; - APP_OP_WRITE_MEDIA_AUDIO = 82; - APP_OP_READ_MEDIA_VIDEO = 83; - APP_OP_WRITE_MEDIA_VIDEO = 84; - APP_OP_READ_MEDIA_IMAGES = 85; - APP_OP_WRITE_MEDIA_IMAGES = 86; - APP_OP_LEGACY_STORAGE = 87; - APP_OP_ACCESS_ACCESSIBILITY = 88; - APP_OP_READ_DEVICE_IDENTIFIERS = 89; - APP_OP_ACCESS_MEDIA_LOCATION = 90; - APP_OP_QUERY_ALL_PACKAGES = 91; - APP_OP_MANAGE_EXTERNAL_STORAGE = 92; - APP_OP_INTERACT_ACROSS_PROFILES = 93; - APP_OP_ACTIVATE_PLATFORM_VPN = 94; - APP_OP_LOADER_USAGE_STATS = 95; - APP_OP_DEPRECATED_1 = 96 [deprecated = true]; - APP_OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97; - APP_OP_AUTO_REVOKE_MANAGED_BY_INSTALLER = 98; - APP_OP_NO_ISOLATED_STORAGE = 99; - APP_OP_PHONE_CALL_MICROPHONE = 100; - APP_OP_PHONE_CALL_CAMERA = 101; - APP_OP_RECORD_AUDIO_HOTWORD = 102; - APP_OP_MANAGE_ONGOING_CALLS = 103; - APP_OP_MANAGE_CREDENTIALS = 104; -} diff --git a/core/proto/android/app/job/enums.proto b/core/proto/android/app/job/enums.proto deleted file mode 100644 index 41863bbbfbf1..000000000000 --- a/core/proto/android/app/job/enums.proto +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.app.job; - -// This file is for JobScheduler enums inside the app directory. If you're -// adding enums for system-server-side code, use the file in -// frameworks/base/core/proto/android/server/job. -option java_outer_classname = "JobProtoEnums"; -option java_multiple_files = true; - -// Reasons a job is stopped. -// Primarily used in android.app.job.JobParameters.java. -enum StopReasonEnum { - STOP_REASON_UNKNOWN = -1; - STOP_REASON_CANCELLED = 0; - STOP_REASON_CONSTRAINTS_NOT_SATISFIED = 1; - STOP_REASON_PREEMPT = 2; - STOP_REASON_TIMEOUT = 3; - STOP_REASON_DEVICE_IDLE = 4; - STOP_REASON_DEVICE_THERMAL = 5; - STOP_REASON_RESTRICTED_BUCKET = 6; -} diff --git a/core/proto/android/app/media_output_enum.proto b/core/proto/android/app/media_output_enum.proto deleted file mode 100644 index 0d42fb77025a..000000000000 --- a/core/proto/android/app/media_output_enum.proto +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.app.settings.mediaoutput; -option java_multiple_files = true; - -/** - * The medium type specified in an output switching operation. - */ -enum MediumType { - UNKNOWN_TYPE = 0; - BUILTIN_SPEAKER = 1; - WIRED_3POINT5_MM_AUDIO = 100; - WIRED_3POINT5_MM_HEADSET = 101; - WIRED_3POINT5_MM_HEADPHONES = 102; - USB_C_AUDIO = 200; - USB_C_DEVICE = 201; - USB_C_HEADSET = 202; - USB_C_ACCESSORY = 203; - USB_C_DOCK = 204; - USB_C_HDMI = 205; - BLUETOOTH = 300; - BLUETOOTH_HEARING_AID = 301; - BLUETOOTH_A2DP = 302; - REMOTE_SINGLE = 400; - REMOTE_TV = 401; - REMOTE_SPEAKER = 402; - REMOTE_GROUP = 500; - REMOTE_DYNAMIC_GROUP = 501; -}; - -/** - * The result of an output switching operation. - */ -enum SwitchResult { - ERROR = 0; - OK = 1; -}; - -/** - * The sub result of an output switching operation. - */ -enum SubResult { - UNKNOWN_ERROR = 0; - NO_ERROR = 1; - REJECTED = 2; - NETWORK_ERROR = 3; - ROUTE_NOT_AVAILABLE = 4; - INVALID_COMMAND = 5; -} diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto deleted file mode 100644 index a2a7649645f5..000000000000 --- a/core/proto/android/app/settings_enums.proto +++ /dev/null @@ -1,2794 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.app.settings; -option java_multiple_files = true; - -/** - * The action performed in this event - */ -enum Action { - ACTION_UNKNOWN = 0; - PAGE_VISIBLE = 1; - PAGE_HIDE = 2; - - // ACTION: Settings > Wi-Fi > [Long press network] > Connect to network - // SUBTYPE: true if connecting to a saved network, false if not - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_WIFI_CONNECT = 135; - - // ACTION: Settings > Wi-Fi > [Long press network] > Forget network - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_WIFI_FORGET = 137; - - // ACTION: Settings > Wi-Fi > Toggle off - // SUBTYPE: true if connected to network before toggle, false if not - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_WIFI_OFF = 138; - - // ACTION: Settings > Wi-Fi > Toggle on - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_WIFI_ON = 139; - - // ACTION: Settings > Bluetooth > Overflow > Rename this device - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_BLUETOOTH_RENAME = 161; - - // ACTION: Settings > Bluetooth > Overflow > Show received files - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_BLUETOOTH_FILES = 162; - - // ACTION: DND Settings > Priority only allows > Reminder toggle - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_ZEN_ALLOW_REMINDERS = 167; - - // ACTION: DND Settings > Priority only allows > Event toggle - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_ZEN_ALLOW_EVENTS = 168; - - // ACTION: DND Settings > Priority only allows > Messages - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_ZEN_ALLOW_MESSAGES = 169; - - // ACTION: DND Settings > Priority only allows > Calls - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_ZEN_ALLOW_CALLS = 170; - - // ACTION: DND Settings > Priority only allows > Repeat callers toggle - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_ZEN_ALLOW_REPEAT_CALLS = 171; - - // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule > Delete - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_ZEN_DELETE_RULE_OK = 175; - - // ACTION: Settings > More > Airplane mode toggle - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_AIRPLANE_TOGGLE = 177; - - // ACTION: Settings > Data usage > Cellular data toggle - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_CELL_DATA_TOGGLE = 178; - - // ACTION: Settings > Display > When device is rotated - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_ROTATION_LOCK = 203; - - // OPEN: Settings > Search > Perform search - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_SEARCH_RESULTS = 226; - - // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Delete - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_FINGERPRINT_DELETE = 253; - - // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Rename - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_FINGERPRINT_RENAME = 254; - - // ACTION: Settings -> Developer Options -> Take bug report -> Interactive report - // CATEGORY: SETTINGS - // OS: N - // Interactive bug report initiated from Settings. - ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE = 294; - - // ACTION: Settings -> Developer Options -> Take bug report -> Full report - // CATEGORY: SETTINGS - // OS: N - // Interactive bug report initiated from Settings. - ACTION_BUGREPORT_FROM_SETTINGS_FULL = 295; - - // click on collapsed conditional or clicks expand button - ACTION_SETTINGS_CONDITION_EXPAND = 373; - - // click main area of expanded conditional - ACTION_SETTINGS_CONDITION_CLICK = 375; - - // click a direct button on expanded conditional - ACTION_SETTINGS_CONDITION_BUTTON = 376; - - // Action: user enable / disabled data saver using Settings - // OPEN: Settings -> Data Usage -> Data saver -> On/off toggle - // VALUE: 1 for enabled, 0 for disabled - // CATEGORY: SETTINGS - // OS: N - ACTION_DATA_SAVER_MODE = 394; - - // User whitelisted an app for Data Saver mode; action pass package name of app - // Action: user enable / disabled data saver using Settings - // OPEN: Settings -> Data Usage -> Data saver -> Unrestricted data access > APP toggle turned on - // or - // Settings -> Apps -> APP -> Data usage -> Unrestricted data usage toggle turned on - // VALUE: package name of APP - // CATEGORY: SETTINGS - // OS: N - ACTION_DATA_SAVER_WHITELIST = 395; - - // User blacklisted an app for Data Saver mode; action pass package name of app - // OPEN: Settings -> Apps -> APP -> Data usage -> Background data toggle turned off - // VALUE: package name of APP - // CATEGORY: SETTINGS - // OS: N - ACTION_DATA_SAVER_BLACKLIST = 396; - - // ACTION: Settings -> Storage -> Manage storage -> Click Storage Manager - // SUBTYPE: false is off, true is on - ACTION_TOGGLE_STORAGE_MANAGER = 489; - - // OPEN: Settings > Display -> Ambient Display - // CATEGORY: SETTINGS - ACTION_AMBIENT_DISPLAY = 495; - - // ACTION: Allow Battery optimization for an app - APP_SPECIAL_PERMISSION_BATTERY_ALLOW = 764; - - // ACTION: Deny Battery optimization for an app - APP_SPECIAL_PERMISSION_BATTERY_DENY = 765; - - // ACTION: Enable Device Admin app - APP_SPECIAL_PERMISSION_ADMIN_ALLOW = 766; - - // ACTION: Disable Device Admin app - APP_SPECIAL_PERMISSION_ADMIN_DENY = 767; - - // ACTION: Allow "Do Not Disturb access" for an app - APP_SPECIAL_PERMISSION_DND_ALLOW = 768; - - // ACTION: Deny "Do Not Disturb access" for an app - APP_SPECIAL_PERMISSION_DND_DENY = 769; - - // ACTION: Allow "Draw over other apps" for an app - APP_SPECIAL_PERMISSION_APPDRAW_ALLOW = 770; - - // ACTION: Deny "Display over other apps" for an app - APP_SPECIAL_PERMISSION_APPDRAW_DENY = 771; - - // ACTION: Allow "VR helper services" for an app - APP_SPECIAL_PERMISSION_VRHELPER_ALLOW = 772; - - // ACTION: Deny "VR helper services" for an app - APP_SPECIAL_PERMISSION_VRHELPER_DENY = 773; - - // ACTION: Allow "Modify system settings" for an app - APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_ALLOW = 774; - - // ACTION: Deny "Modify system settings" for an app - APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_DENY = 775; - - // ACTION: Allow "Notification access" for an app - APP_SPECIAL_PERMISSION_NOTIVIEW_ALLOW = 776; - - // ACTION: Deny "Notification access" for an app - APP_SPECIAL_PERMISSION_NOTIVIEW_DENY = 777; - - // ACTION: "Premium SMS access" for an app - "ask user" option - APP_SPECIAL_PERMISSION_PREMIUM_SMS_ASK = 778; - - // ACTION: "Premium SMS access" for an app - "never allow" option - APP_SPECIAL_PERMISSION_PREMIUM_SMS_DENY = 779; - - // ACTION: "Premium SMS access" for an app - "always allow" option - APP_SPECIAL_PERMISSION_PREMIUM_SMS_ALWAYS_ALLOW = 780; - - // ACTION: Allow "Unrestricted data access" for an app - APP_SPECIAL_PERMISSION_UNL_DATA_ALLOW = 781; - - // ACTION: Deny "Unrestricted data access" for an app - APP_SPECIAL_PERMISSION_UNL_DATA_DENY = 782; - - // ACTION: Allow "Usage access" for an app - APP_SPECIAL_PERMISSION_USAGE_VIEW_ALLOW = 783; - - // ACTION: Deny "Usage access" for an app - APP_SPECIAL_PERMISSION_USAGE_VIEW_DENY = 784; - - // ACTION: "Force stop" action on an app - ACTION_APP_FORCE_STOP = 807; - - // ACTION: Allow "Enable picture-in-picture" for an app - APP_PICTURE_IN_PICTURE_ALLOW = 813; - - // ACTION: Create a Settings shortcut item. - ACTION_SETTINGS_CREATE_SHORTCUT = 829; - - // ACTION: A tile in Settings information architecture is clicked - ACTION_SETTINGS_TILE_CLICK = 830; - - // ACTION: Settings advanced button is expanded - ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND = 834; - - // ACTION: Deny "Enable picture-in-picture" for an app - APP_PICTURE_IN_PICTURE_DENY = 814; - - // ACTION: Settings -> Display -> Theme - ACTION_THEME = 816; - - // ACTION: Settings > About device > Build number - ACTION_SETTINGS_BUILD_NUMBER_PREF = 847; - - // ACTION: Settings > Battery > Menu > Optimization - ACTION_SETTINGS_MENU_BATTERY_OPTIMIZATION = 851; - - // ACTION: Settings > Battery > Menu > Apps Toggle - ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE = 852; - - // ACTION: Settings > Any preference is changed - ACTION_SETTINGS_PREFERENCE_CHANGE = 853; - - // ACTION: Settings > Connected devices > Bluetooth -> Available devices - ACTION_SETTINGS_BLUETOOTH_PAIR = 866; - - // ACTION: Settings > Connected devices > Bluetooth -> Paired devices - ACTION_SETTINGS_BLUETOOTH_CONNECT = 867; - - // ACTION: Settings > Connected devices > Bluetooth -> Connected device - ACTION_SETTINGS_BLUETOOTH_DISCONNECT = 868; - - // ACTION: Settings > Connected devices > Bluetooth -> Error dialog - ACTION_SETTINGS_BLUETOOTH_CONNECT_ERROR = 869; - - // ACTION: Settings > Connected devices > Bluetooth master switch Toggle - ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE = 870; - - // ACTION: Settings > App detail > Uninstall - ACTION_SETTINGS_UNINSTALL_APP = 872; - - // ACTION: Settings > App detail > Uninstall Device admin app - ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN = 873; - - // ACTION: Settings > App detail > Disable app - ACTION_SETTINGS_DISABLE_APP = 874; - - // ACTION: Settings > App detail > Enable app - ACTION_SETTINGS_ENABLE_APP = 875; - - // ACTION: Settings > App detail > Clear data - ACTION_SETTINGS_CLEAR_APP_DATA = 876; - - // ACTION: Settings > App detail > Clear cache - ACTION_SETTINGS_CLEAR_APP_CACHE = 877; - - // ACTION: Logs pressing the "Clear app" button in the app info settings page for an instant - // app. - // VALUE: The package name of the app - ACTION_SETTINGS_CLEAR_INSTANT_APP = 923; - - // OPEN: Assist Gesture training intro in Settings - // CATEGORY: SETTINGS - // OS: O DR - SETTINGS_ASSIST_GESTURE_TRAINING_INTRO = 991; - - // OPEN: Assist Gesture training enrolling in Settings - // CATEGORY: SETTINGS - // OS: O DR - SETTINGS_ASSIST_GESTURE_TRAINING_ENROLLING = 992; - - // OPEN: Assist Gesture training finished in Settings - // CATEGORY: SETTINGS - // OS: O DR - SETTINGS_ASSIST_GESTURE_TRAINING_FINISHED = 993; - - // ACTION: Update default app from Settings - ACTION_SETTINGS_UPDATE_DEFAULT_APP = 1000; - - // ACTION: Settings > Wi-Fi > [Long press network] > Sign in to network - // CATEGORY: SETTINGS - // OS: O DR - ACTION_WIFI_SIGNIN = 1008; - - // ACTION: Settings > Notification Settings > Open application notification - // CATEGORY: SETTINGS - // OS: O DR - ACTION_OPEN_APP_NOTIFICATION_SETTING = 1016; - - // ACTION: Settings > App Info > Open app settings - // CATEGORY: SETTINGS - // OS: O DR - ACTION_OPEN_APP_SETTING = 1017; - - // ACTION: Collect PSD Signals - // CATEGORY: SETTINGS - // OS: O DR - ACTION_PSD_LOADER = 1019; - - // OPEN: Settings > Trampoline Intent > Settings page - // CATEGORY: SETTINGS - // OS: O DR - TRAMPOLINE_SETTINGS_EVENT = 1033; - - // ACTION: Logged when user tries to pair a Bluetooth device without name from Settings app - // CATEGORY: SETTINGS - // OS: O MR - ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES = 1096; - - // ACTION: Settings > Network & Internet > Mobile network > Network - // CATEGORY: SETTINGS - ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK = 1210; - - // ACTION: DND Settings > Priority only allows > Alarms toggle - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: P - ACTION_ZEN_ALLOW_ALARMS = 1226; - - // ACTION: DND Settings > Priority only allows > Media toggle - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: P - ACTION_ZEN_ALLOW_MEDIA = 1227; - - // ACTION: A private dns mode been selected by user - // CATEGORY: SETTINGS - // OS: P - ACTION_PRIVATE_DNS_MODE = 1249; - - // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Select rule ("Event") > Rule name > OK - // CATEGORY: SETTINGS - // OS: P - ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK = 1267; - - // OPEN: Settings > Sound > Do Not Disturb > TURN ON NOW/TURN OFF NOW - // CATEGORY: SETTINGS - // OS: P - ACTION_ZEN_TOGGLE_DND_BUTTON = 1268; - - // ACTION: DND Settings > What to block > full screen intents - // SUBTYPE: false is allowed, true is blocked - // CATEGORY: SETTINGS - // OS: 6.0 - ACTION_ZEN_BLOCK_FULL_SCREEN_INTENTS = 1332; - - // ACTION: DND Settings > What to block - // SUBTYPE: false is allowed, true is blocked - // OS: P - ACTION_ZEN_BLOCK_LIGHT = 1333; - - // ACTION: DND Settings > What to block - // SUBTYPE: false is allowed, true is blocked - // OS: P - ACTION_ZEN_BLOCK_PEEK = 1334; - - // ACTION: DND Settings > What to block - // SUBTYPE: false is allowed, true is blocked - // OS: P - ACTION_ZEN_BLOCK_STATUS = 1335; - - // ACTION: DND Settings > What to block - // SUBTYPE: false is allowed, true is blocked - // OS: P - ACTION_ZEN_BLOCK_BADGE = 1336; - - // ACTION: DND Settings > What to block - // SUBTYPE: false is allowed, true is blocked - // OS: P - ACTION_ZEN_BLOCK_AMBIENT = 1337; - - // ACTION: DND Settings > What to block - // SUBTYPE: false is allowed, true is blocked - // OS: P - ACTION_ZEN_BLOCK_NOTIFICATION_LIST = 1338; - - // ACTION: DND Settings > Priority only allows > System toggle - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: P - ACTION_ZEN_ALLOW_SYSTEM = 1340; - - // ACTION: Settings > Battery settings > Battery tip > App restriction tip - // OS: P - ACTION_APP_RESTRICTION_TIP = 1347; - - // ACTION: Settings > Battery settings > Battery tip > High usage tip - // OS: P - ACTION_HIGH_USAGE_TIP = 1348; - - // ACTION: Settings > Battery settings > Battery tip > Summary tip - // OS: P - ACTION_SUMMARY_TIP = 1349; - - // ACTION: Settings > Battery settings > Battery tip > Smart battery tip - // OS: P - ACTION_SMART_BATTERY_TIP = 1350; - - // ACTION: Settings > Battery settings > Battery tip > Early warning tip - // OS: P - ACTION_EARLY_WARNING_TIP = 1351; - - // ACTION: Settings > Battery settings > Battery tip > Low battery tip - // OS: P - ACTION_LOW_BATTERY_TIP = 1352; - - // ACTION: Settings > Battery settings > Battery tip > App restriction list shown - // OS: P - ACTION_APP_RESTRICTION_TIP_LIST = 1353; - - // ACTION: Settings > Battery settings > Battery tip > High usage list shown - // OS: P - ACTION_HIGH_USAGE_TIP_LIST = 1354; - - // ACTION: Settings > Battery settings > Battery tip > Open app restriction page - // CATEGORY: SETTINGS - // OS: P - ACTION_TIP_OPEN_APP_RESTRICTION_PAGE = 1361; - - // ACTION: Settings > Battery settings > Battery tip > Restrict app - // CATEGORY: SETTINGS - // OS: P - ACTION_TIP_RESTRICT_APP = 1362; - - // ACTION: Settings > Battery settings > Battery tip > Unrestrict app - // CATEGORY: SETTINGS - // OS: P - ACTION_TIP_UNRESTRICT_APP = 1363; - - // ACTION: Settings > Battery settings > Battery tip > Open smart battery page - // CATEGORY: SETTINGS - // OS: P - ACTION_TIP_OPEN_SMART_BATTERY = 1364; - - // ACTION: Settings > Battery settings > Battery tip > Turn on battery saver - // CATEGORY: SETTINGS - // OS: P - ACTION_TIP_TURN_ON_BATTERY_SAVER = 1365; - - // ACTION: Settings > Anomaly receiver > Anomaly received - // CATEGORY: SETTINGS - // OS: P - ACTION_ANOMALY_TRIGGERED = 1367; - - // ACTION: A Settings Slice is requested - // CATEGORY: SETTINGS - // OS: P - ACTION_SETTINGS_SLICE_REQUESTED = 1371; - - // ACTION: A Settings Slice is updated with new value - // CATEGORY: SETTINGS - // OS: P - ACTION_SETTINGS_SLICE_CHANGED = 1372; - - // OPEN: DND onboarding activity > Ok button - // CATEGORY: SETTINGS - // OS: P - ACTION_ZEN_ONBOARDING_OK = 1378; - - // OPEN: DND onboarding activity > Settings link - // CATEGORY: SETTINGS - // OS: P - ACTION_ZEN_ONBOARDING_SETTINGS = 1379; - - // ACTION: Settings > Anomaly receiver > Anomaly ignored, don't show up in battery settings - // CATEGORY: SETTINGS - // OS: P - ACTION_ANOMALY_IGNORED = 1387; - - // ACTION: Settings > Battery settings > Battery tip > Open battery saver page - // CATEGORY: SETTINGS - // OS: P - ACTION_TIP_OPEN_BATTERY_SAVER_PAGE = 1388; - - // ACTION: DND Settings > What to block - // OS: P - ACTION_ZEN_SOUND_ONLY = 1396; - - // ACTION: DND Settings > Notifications - // OS: P - ACTION_ZEN_SOUND_AND_VIS_EFFECTS = 1397; - - // ACTION: DND Settings > Notifications - // OS: P - ACTION_ZEN_SHOW_CUSTOM = 1398; - - // ACTION: DND Settings > Notifications - // OS: P - ACTION_ZEN_CUSTOM = 1399; - - // OPEN: DND onboarding activity > don't update button - // CATEGORY: SETTINGS - // OS: P - ACTION_ZEN_ONBOARDING_KEEP_CURRENT_SETTINGS = 1406; - - // ACTION: Storage initialization wizard initialization choice of external/portable - // CATEGORY: SETTINGS - // OS: P - ACTION_STORAGE_INIT_EXTERNAL = 1407; - - // ACTION: Storage initialization wizard initialization choice of internal/adoptable - // CATEGORY: SETTINGS - // OS: P - ACTION_STORAGE_INIT_INTERNAL = 1408; - - // ACTION: Storage initialization wizard benchmark fast choice of continue - // CATEGORY: SETTINGS - // OS: P - ACTION_STORAGE_BENCHMARK_FAST_CONTINUE = 1409; - - // ACTION: Storage initialization wizard benchmark slow choice of continue - // CATEGORY: SETTINGS - // OS: P - ACTION_STORAGE_BENCHMARK_SLOW_CONTINUE = 1410; - - // ACTION: Storage initialization wizard benchmark slow choice of abort - // CATEGORY: SETTINGS - // OS: P - ACTION_STORAGE_BENCHMARK_SLOW_ABORT = 1411; - - // ACTION: Storage initialization wizard migration choice of now - // CATEGORY: SETTINGS - // OS: P - ACTION_STORAGE_MIGRATE_NOW = 1412; - - // ACTION: Storage initialization wizard migration choice of later - // CATEGORY: SETTINGS - // OS: P - ACTION_STORAGE_MIGRATE_LATER = 1413; - - // OPEN: Settings > Sound > Switch a2dp devices dialog - // CATEGORY: SETTINGS - // OS: P - DIALOG_SWITCH_A2DP_DEVICES = 1415; - - - // OPEN: Settings > Sound > Switch hfp devices dialog - // CATEGORY: SETTINGS - // OS: P - DIALOG_SWITCH_HFP_DEVICES = 1416; - - // OPEN: QS Sensor Privacy Mode tile shown - // ACTION: QS Sensor Privacy Mode tile tapped - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: QUICK_SETTINGS - // OS: Q - QS_SENSOR_PRIVACY = 1598; - - // ACTION: Tap & Pay -> Default Application Setting -> Use Forground - ACTION_NFC_PAYMENT_FOREGROUND_SETTING = 1622; - - // ACTION: Tap & Pay -> Default Application Setting -> Use Default - ACTION_NFC_PAYMENT_ALWAYS_SETTING = 1623; - - // ACTION: Settings > Search Bar > Avatar - // CATEGORY: SETTINGS - // OS: Q - CLICK_ACCOUNT_AVATAR = 1643; - - // ACTION: Set new password (action intent android.app.action.SET_NEW_PASSWORD) - // CATEGORY: SETTINGS - // OS: Q - ACTION_SET_NEW_PASSWORD = 1645; - - // ACTION: Set new password (action intent android.app.action.SET_NEW_PARENT_PROFILE_PASSWORD) - // CATEGORY: SETTINGS - // OS: Q - ACTION_SET_NEW_PARENT_PROFILE_PASSWORD = 1646; - - // ACTION: An interaction with a Slice or other component in the Panel. - // CATEGORY: SETTINGS - // OS: Q - ACTION_PANEL_INTERACTION = 1658; - - // ACTION: Show Contextual homepage. Log total loading latency. - ACTION_CONTEXTUAL_HOME_SHOW = 1662; - - // ACTION: Contextual card displays - ACTION_CONTEXTUAL_CARD_SHOW = 1663; - - // ACTION: Contextual cards are eligible to be shown, but don't rank high - ACTION_CONTEXTUAL_CARD_NOT_SHOW = 1664; - - // ACTION: Settings > long press a card, and click dismiss - // Contextual card is dismissed - ACTION_CONTEXTUAL_CARD_DISMISS = 1665; - - // ACTION: Settings > click a card - // Contextual card is clicked - ACTION_CONTEXTUAL_CARD_CLICK = 1666; - - // Mapping: go/at-mapping - ACTION_ATSG = 1674; - - ACTION_ATPG = 1675; - - ACTION_ATCLPB = 1676; - - ACTION_ATCGIB = 1677; - - ACTION_ATCPAB = 1678; - - ACTION_ATCSAUC = 1679; - - ACTION_ATCSCUC = 1680; - - ACTION_ATCHNUC = 1681; - - // ACTION: Individual contextual card loading time - ACTION_CONTEXTUAL_CARD_LOAD = 1684; - - //ACTION: Contextual card loading timeout - ACTION_CONTEXTUAL_CARD_LOAD_TIMEOUT = 1685; - - //ACTION: Log result for each card's eligibility check - ACTION_CONTEXTUAL_CARD_ELIGIBILITY = 1686; - - // ACTION: Display white balance setting enabled or disabled. - // CATEGORY: SETTINGS - // OS: Q - ACTION_DISPLAY_WHITE_BALANCE_SETTING_CHANGED = 1703; - - // ACTION: Share a Wi-Fi network by generating a QR code - ACTION_SETTINGS_SHARE_WIFI_QR_CODE = 1710; - - // ACTION: Connect to a Wi-Fi network by scanning a QR code - ACTION_SETTINGS_ENROLL_WIFI_QR_CODE = 1711; - - // ACTION: Share Wi-Fi hotspot by generating a QR code - ACTION_SETTINGS_SHARE_WIFI_HOTSPOT_QR_CODE = 1712; - - // ACTION: Settings > Initialize Search bar > Verify Slice > Invalid data - ACTION_VERIFY_SLICE_ERROR_INVALID_DATA = 1725; - - // ACTION: Settings > Initialize Search bar > Verify Slice > Parsing error - ACTION_VERIFY_SLICE_PARSING_ERROR = 1726; - - // ACTION: Settings > Initialize Search bar > Verify Slice > Other exception - ACTION_VERIFY_SLICE_OTHER_EXCEPTION = 1727; - - // Custom tag to evaluate the consuming time of the Controller.updateState. - // CATEGORY: SETTINGS - // OS: R - ACTION_CONTROLLER_UPDATE_STATE = 1728; - - // Custom tag to evaluate the consuming time from onAttach to - // DashboardFragment.updatePreferenceStates. - // CATEGORY: SETTINGS - // OS: R - ACTION_DASHBOARD_VISIBLE_TIME = 1729; - - // ACTION: Allow "Access all files" for an app - APP_SPECIAL_PERMISSION_MANAGE_EXT_STRG_ALLOW = 1730; - - // ACTION: Deny "Access all files" for an app - APP_SPECIAL_PERMISSION_MANAGE_EXT_STRG_DENY = 1731; - - // ACTION: Battery feature usage - ACTION_BATTERY_OPTION_FEATURE_USAGE = 1732; - - // ACTION: Battery feature runtime event - ACTION_BATTERY_OPTION_RUNTIME_EVENT = 1733; - - // ACTION: Settings > Developer Options > Toggle on Wireless debugging - // CATEGORY: SETTINGS - // OS: R - ACTION_ADB_WIRELESS_ON = 1734; - - // ACTION: Settings > Developer Options > Toggle off Wireless debugging - // CATEGORY: SETTINGS - // OS: R - ACTION_ADB_WIRELESS_OFF = 1735; - - // ACTION: Change Wi-Fi hotspot name - // CATEGORY: SETTINGS - // OS: R - ACTION_SETTINGS_CHANGE_WIFI_HOTSPOT_NAME = 1736; - - // ACTION: Change Wi-Fi hotspot password - // CATEGORY: SETTINGS - // OS: R - ACTION_SETTINGS_CHANGE_WIFI_HOTSPOT_PASSWORD = 1737; - - // ACTION: Settings > Security > Toggle on Confirm Sim deletion - // CATEGORY: SETTINGS - // OS: R - ACTION_CONFIRM_SIM_DELETION_ON = 1738; - - // ACTION: Settings > Security > Toggle off Confirm Sim deletion - // CATEGORY: SETTINGS - // OS: R - ACTION_CONFIRM_SIM_DELETION_OFF = 1739; - - // ACTION: Settings > System > Gestures > Double tap > Toggle on Double tap - // CATEGORY: SETTINGS - // OS: S - ACTION_COLUMBUS_ENABLED = 1740; - - // ACTION: Settings > System > Gestures > Double tap > Toggle off Double tap - // CATEGORY: SETTINGS - // OS: S - ACTION_COLUMBUS_DISABLED = 1741; - - // ACTION: Settings > System > Gestures > Double tap > Invoke Assistant - // CATEGORY: SETTINGS - // OS: S - ACTION_COLUMBUS_ACTION_ASSISTANT = 1742; - - // ACTION: Settings > System > Gestures > Double tap > Take screenshot - // CATEGORY: SETTINGS - // OS: S - ACTION_COLUMBUS_ACTION_SCREENSHOT = 1743; - - // ACTION: Settings > System > Gestures > Double tap > Play and pause - // CATEGORY: SETTINGS - // OS: S - ACTION_COLUMBUS_ACTION_PLAY_PAUSE = 1744; - - // ACTION: Settings > System > Gestures > Double tap > Open app overview - // CATEGORY: SETTINGS - // OS: S - ACTION_COLUMBUS_ACTION_OVERVIEW = 1745; - - // ACTION: Settings > System > Gestures > Double tap > Open notification shade - // CATEGORY: SETTINGS - // OS: S - ACTION_COLUMBUS_ACTION_NOTIFICATION_SHADE = 1746; - - // ACTION: Settings > System > Gestures > Double tap > Require harder taps - // CATEGORY: SETTINGS - // OS: S - ACTION_COLUMBUS_LOW_SENSITIVITY = 1747; - - // OPEN: Columbus Gesture training intro in Settings - // CATEGORY: SETTINGS - // OS: S - SETTINGS_COLUMBUS_GESTURE_TRAINING_INTRO = 1748; - - // OPEN: Columbus Gesture training enrolling in Settings - // CATEGORY: SETTINGS - // OS: S - SETTINGS_COLUMBUS_GESTURE_TRAINING_ENROLLING = 1749; - - // OPEN: Columbus Gesture training finished in Settings - // CATEGORY: SETTINGS - // OS: S - SETTINGS_COLUMBUS_GESTURE_TRAINING_FINISHED = 1750; -} - -/** - * Id for Settings pages. Each page must have its own unique Id. - */ -enum PageId { - // Unknown page. Should not be used in production code. - PAGE_UNKNOWN = 0; - - // OPEN: Settings > Accessibility - // CATEGORY: SETTINGS - // OS: 6.0 - ACCESSIBILITY = 2; - - // OPEN: Settings > Accessibility > Captions preference - // CATEGORY: SETTINGS - // OS: 6.0 - ACCESSIBILITY_CAPTION_PROPERTIES = 3; - - // OPEN: Settings > Accessibility > [Service] - // CATEGORY: SETTINGS - // OS: 6.0 - ACCESSIBILITY_SERVICE = 4; - - // OPEN: Settings > Accessibility > Color correction - // CATEGORY: SETTINGS - // OS: 6.0 - ACCESSIBILITY_TOGGLE_DALTONIZER = 5; - - // OPEN: Settings > Accessibility > Accessibility shortcut - // CATEGORY: SETTINGS - // OS: 6.0 - ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6; - - // OPEN: Settings > Accessibility > Magnification gestures (Renamed in O) - // OPEN: Settings > Accessibility > Magnification > Magnify with triple-tap - // OPEN: Settings > Accessibility > Magnification > Magnify with button - // CATEGORY: SETTINGS - // OS: 6.0 - ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7; - - // OPEN: Settings > Accounts - // CATEGORY: SETTINGS - // OS: 6.0 - ACCOUNT = 8; - - // OPEN: Settings > Accounts > [Single Account Sync Settings] - // CATEGORY: SETTINGS - // OS: 6.0 - ACCOUNTS_ACCOUNT_SYNC = 9; - - // OPEN: Settings > Accounts > Add an account - // CATEGORY: SETTINGS - // OS: 6.0 - ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10; - - // OPEN: Settings > Cellular network settings > APNs - // CATEGORY: SETTINGS - // OS: 6.0 - APN = 12; - - // OPEN: Settings > More > Cellular network settings > APNs > [Edit APN] - // CATEGORY: SETTINGS - // OS: 6.0 - APN_EDITOR = 13; - - // OPEN: Settings > Apps > Configure apps > App links > [App] - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_APP_LAUNCH = 17; - - // OPEN: Settings > Internal storage > Apps storage > [App] - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_APP_STORAGE = 19; - - // OPEN: Settings > Apps > [App info] - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_INSTALLED_APP_DETAILS = 20; - - // OPEN: Settings > Memory > App usage > [App Memory usage] - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_PROCESS_STATS_DETAIL = 21; - - // OPEN: Settings > Memory > App usage - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_PROCESS_STATS_UI = 23; - - // OPEN: Choose Bluetooth device (ex: when sharing) - // CATEGORY: SETTINGS - // OS: 6.0 - BLUETOOTH_DEVICE_PICKER = 25; - - // OPEN: Settings > Security > Choose screen lock - // CATEGORY: SETTINGS - // OS: 6.0 - CHOOSE_LOCK_GENERIC = 27; - - // OPEN: Settings > Security > Choose screen lock > Choose your password - // CATEGORY: SETTINGS - // OS: 6.0 - CHOOSE_LOCK_PASSWORD = 28; - - // OPEN: Settings > Security > Choose screen lock > Choose your pattern - // CATEGORY: SETTINGS - // OS: 6.0 - CHOOSE_LOCK_PATTERN = 29; - - // OPEN: Settings > Security > Choose screen lock > Confirm your password - // CATEGORY: SETTINGS - // OS: 6.0 - CONFIRM_LOCK_PASSWORD = 30; - - // OPEN: Settings > Security > Choose screen lock > Confirm your pattern - // CATEGORY: SETTINGS - // OS: 6.0 - CONFIRM_LOCK_PATTERN = 31; - - // OPEN: Settings > Security > Encrypt phone - // CATEGORY: SETTINGS - // OS: 6.0 - CRYPT_KEEPER = 32; - - // OPEN: Settings > Security > Encrypt phone > Confirm - // CATEGORY: SETTINGS - // OS: 6.0 - CRYPT_KEEPER_CONFIRM = 33; - - // OPEN: Settings (Root page) - // CATEGORY: SETTINGS - // OS: 6.0 - DASHBOARD_SUMMARY = 35; - - // OPEN: Settings > Data usage - // CATEGORY: SETTINGS - // OS: 6.0 - DATA_USAGE_SUMMARY = 37; - - // OPEN: Settings > Date & time - // CATEGORY: SETTINGS - // OS: 6.0 - DATE_TIME = 38; - - // OPEN: Settings > Developer options - // CATEGORY: SETTINGS - // OS: 6.0 - DEVELOPMENT = 39; - - // OPEN: Settings > About phone - // CATEGORY: SETTINGS - // OS: 6.0 - DEVICEINFO = 40; - - // OPEN: Settings > Internal storage - // CATEGORY: SETTINGS - // OS: 6.0 - DEVICEINFO_STORAGE = 42; - - // OPEN: Settings > Display - // CATEGORY: SETTINGS - // OS: 6.0 - DISPLAY = 46; - - // OPEN: Settings > Display > Daydream - // CATEGORY: SETTINGS - // OS: 6.0 - DREAM = 47; - - // OPEN: Settings > Security > Screen lock > Secure start-up - // CATEGORY: SETTINGS - // OS: 6.0 - ENCRYPTION = 48; - - // OPEN: Settings > Security > Nexus Imprint - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT = 49; - - // OPEN: Settings > Battery > History details - // CATEGORY: SETTINGS - // OS: 6.0 - FUELGAUGE_BATTERY_HISTORY_DETAIL = 51; - - // OPEN: Settings > Battery > Battery saver - // CATEGORY: SETTINGS - // OS: 6.0 - FUELGAUGE_BATTERY_SAVER = 52; - - // OPEN: Settings > Battery > [App Use details] - // CATEGORY: SETTINGS - // OS: 6.0 - FUELGAUGE_POWER_USAGE_DETAIL = 53; - - // OPEN: Settings > Security > SIM card lock settings - // CATEGORY: SETTINGS - // OS: 6.0 - ICC_LOCK = 56; - - // OPEN: Settings > Language & input > Physical keyboard - // CATEGORY: SETTINGS - // OS: 6.0 - INPUTMETHOD_KEYBOARD = 58; - - // OPEN: Settings > Language & input > Spell checker - // CATEGORY: SETTINGS - // OS: 6.0 - INPUTMETHOD_SPELL_CHECKERS = 59; - - // OBSOLETE - INPUTMETHOD_SUBTYPE_ENABLER = 60; - - // OPEN: Settings > Language & input > Personal dictionary - // CATEGORY: SETTINGS - // OS: 6.0 - INPUTMETHOD_USER_DICTIONARY = 61; - - // OPEN: Settings > Language & input > Add word - // CATEGORY: SETTINGS - // OS: 6.0 - INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62; - - // OPEN: Settings > Location - // CATEGORY: SETTINGS - // OS: 6.0 - LOCATION = 63; - - // OPEN: Settings > Apps - // CATEGORY: SETTINGS - // OS: 6.0 - MANAGE_APPLICATIONS = 65; - - // OPEN: Settings > Backup & reset > Factory data reset - // CATEGORY: SETTINGS - // OS: 6.0 - MASTER_CLEAR = 66; - - // OPEN: Settings > Backup & reset > Factory data reset > Confirm - // CATEGORY: SETTINGS - // OS: 6.0 - MASTER_CLEAR_CONFIRM = 67; - - // OPEN: Settings > More > Android Beam - // CATEGORY: SETTINGS - // OS: 6.0 - NFC_BEAM = 69; - - // OPEN: Settings > Tap & pay - // CATEGORY: SETTINGS - // OS: 6.0 - NFC_PAYMENT = 70; - - // OPEN: Settings > Sound & notification > App notifications > [App] - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_APP_NOTIFICATION = 72; - - // OBSOLETE - NOTIFICATION_REDACTION = 74; - - // OPEN: Settings Widget > Notification log - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_STATION = 75; - - // OPEN: Settings > Sound & notification > Do not disturb - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_ZEN_MODE = 76; - - - // OPEN: Print job notification > Print job settings - // CATEGORY: SETTINGS - // OS: 6.0 - PRINT_JOB_SETTINGS = 78; - - // OPEN: Settings > Printing > [Print Service] - // CATEGORY: SETTINGS - // OS: 6.0 - PRINT_SERVICE_SETTINGS = 79; - - // OPEN: Settings > Printing - // CATEGORY: SETTINGS - // OS: 6.0 - PRINT_SETTINGS = 80; - - // OPEN: Settings > Backup & reset - // CATEGORY: SETTINGS - // OS: 6.0 - PRIVACY = 81; - - //OBSOLETE - PROXY_SELECTOR = 82; - - // OPEN: Settings > Backup & reset > Network settings reset - // CATEGORY: SETTINGS - // OS: 6.0 - RESET_NETWORK = 83; - - // OPEN: Settings > Backup & reset > Network settings reset > Confirm - // CATEGORY: SETTINGS - // OS: 6.0 - RESET_NETWORK_CONFIRM = 84; - - // OPEN: Settings > Developer Options > Running Services - // CATEGORY: SETTINGS - // OS: 6.0 - RUNNING_SERVICE_DETAILS = 85; - - // OPEN: Settings > Security > Screen pinning - // CATEGORY: SETTINGS - // OS: 6.0 - SCREEN_PINNING = 86; - - // OPEN: Settings > Security - // CATEGORY: SETTINGS - // OS: 6.0 - SECURITY = 87; - - // OPEN: Settings > SIM cards - // CATEGORY: SETTINGS - // OS: 6.0 - SIM = 88; - - // OBSOLETE - TESTING = 89; - - // OPEN: Settings > More > Tethering & portable hotspot - // CATEGORY: SETTINGS - // OS: 6.0 - TETHER = 90; - - // OPEN: Settings > Security > Trust agents - // CATEGORY: SETTINGS - // OS: 6.0 - TRUST_AGENT = 91; - - // OPEN: Settings > Security > Trusted credentials - // CATEGORY: SETTINGS - // OS: 6.0 - TRUSTED_CREDENTIALS = 92; - - // OPEN: Settings > Language & input > TTS output > [Engine] > Settings - // CATEGORY: SETTINGS - // OS: 6.0 - TTS_ENGINE_SETTINGS = 93; - - // OPEN: Settings > Language & input > Text-to-speech output - // CATEGORY: SETTINGS - // OS: 6.0 - TTS_TEXT_TO_SPEECH = 94; - - // OPEN: Settings > Security > Apps with usage access - // CATEGORY: SETTINGS - // OS: 6.0 - USAGE_ACCESS = 95; - - // OPEN: Settings > Users - // CATEGORY: SETTINGS - // OS: 6.0 - USER = 96; - - // OPEN: Settings > Users > [Restricted profile app & content access] - // CATEGORY: SETTINGS - // OS: 6.0 - USERS_APP_RESTRICTIONS = 97; - - // OPEN: Settings > Users > [User settings] - // CATEGORY: SETTINGS - // OS: 6.0 - USER_DETAILS = 98; - - // OPEN: Settings > More > VPN - // CATEGORY: SETTINGS - // OS: 6.0 - VPN = 100; - - // OPEN: Settings > Display > Choose wallpaper from - // CATEGORY: SETTINGS - // OS: 6.0 - WALLPAPER_TYPE = 101; - - // OPEN: Settings > Display > Cast - // CATEGORY: SETTINGS - // OS: 6.0 - WFD_WIFI_DISPLAY = 102; - - // OPEN: Settings > Wi-Fi - // CATEGORY: SETTINGS - // OS: 6.0 - WIFI = 103; - - // OPEN: Settings > More > Wi-Fi Calling - // CATEGORY: SETTINGS - // OS: 6.0 - WIFI_CALLING = 105; - - // OPEN: Settings > Wi-Fi > Saved networks - // CATEGORY: SETTINGS - // OS: 6.0 - WIFI_SAVED_ACCESS_POINTS = 106; - - // OPEN: Settings > Wi-Fi > Advanced Wi-Fi > Wi-Fi Direct - // CATEGORY: SETTINGS - // OS: 6.0 - WIFI_P2P = 109; - - // OPEN: Settings > Apps > Configure apps > App permissions - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_ADVANCED = 130; - - // OPEN: Settings > Location > Scanning - // CATEGORY: SETTINGS - // OS: 6.0 - LOCATION_SCANNING = 131; - - // OPEN: Settings > Sound & notification > App notifications - // CATEGORY: SETTINGS - // OS: 6.0 - MANAGE_APPLICATIONS_NOTIFICATIONS = 133; - - // OPEN: Settings > Sound & notification > DND > Priority only allows - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_ZEN_MODE_PRIORITY = 141; - - // OPEN: Settings > Sound & notification > DND > Automatic rules - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_ZEN_MODE_AUTOMATION = 142; - - // OPEN: Settings > Sound & notification > DND > [Time based rule] - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144; - - // OPEN: Settings > Apps > Configure apps > App links - // CATEGORY: SETTINGS - // OS: 6.0 - MANAGE_DOMAIN_URLS = 143; - - // OPEN: Settings > Sound & notification > DND > [Event rule] - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_ZEN_MODE_EVENT_RULE = 146; - - // OPEN: Settings > Sound & notification > Notification access - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_ACCESS = 179; - - // OPEN: Settings > Sound & notification > Do Not Disturb access - // CATEGORY: SETTINGS - // OS: 6.0 - NOTIFICATION_ZEN_MODE_ACCESS = 180; - - // OPEN: Settings > Internal storage > Apps storage - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_STORAGE_APPS = 182; - - // OPEN: Settings > Security > Usage access - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_USAGE_ACCESS_DETAIL = 183; - - // OPEN: Settings > Battery > Battery optimization - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_HIGH_POWER_APPS = 184; - - // OPEN: Settings > Apps > Configure > Default apps > Assist & voice input - // CATEGORY: SETTINGS - // OS: 6.0 - APPLICATIONS_MANAGE_ASSIST = 201; - - // OPEN: Settings > Memory - // CATEGORY: SETTINGS - // OS: 6.0 - PROCESS_STATS_SUMMARY = 202; - - // OPEN: Settings > Apps > Configure Apps > Display over other apps - // CATEGORY: SETTINGS - // OS: 6.0 - SYSTEM_ALERT_WINDOW_APPS = 221; - - // OPEN: Settings > About phone > Legal information - // CATEGORY: SETTINGS - // OS: 6.0 - ABOUT_LEGAL_SETTINGS = 225; - - - // OPEN: Settings > Developer options > Inactive apps - // CATEGORY: SETTINGS - // OS: 6.0 - FUELGAUGE_INACTIVE_APPS = 238; - - // OPEN: Settings > Security > Nexus Imprint > Add Fingerprint - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_ENROLLING = 240; - // OPEN: Fingerprint Enroll > Find Sensor - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_FIND_SENSOR = 241; - - // OPEN: Fingerprint Enroll > Fingerprint Enrolled! - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_ENROLL_FINISH = 242; - - // OPEN: Fingerprint Enroll introduction - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_ENROLL_INTRO = 243; - - // OPEN: Fingerprint Enroll > Let's Start! - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_ENROLL_SIDECAR = 245; - - // OPEN: Fingerprint Enroll SUW > Let's Start! - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_ENROLLING_SETUP = 246; - - // OPEN: Fingerprint Enroll SUW > Find Sensor - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_FIND_SENSOR_SETUP = 247; - - // OPEN: Fingerprint Enroll SUW > Fingerprint Enrolled! - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_ENROLL_FINISH_SETUP = 248; - - // OPEN: Fingerprint Enroll SUW introduction - // CATEGORY: SETTINGS - // OS: 6.0 - FINGERPRINT_ENROLL_INTRO_SETUP = 249; - - // OPEN: Settings > Developer Options > Background Check - // CATEGORY: SETTINGS - // OS: N - BACKGROUND_CHECK_SUMMARY = 258; - - // OPEN: Settings > Notifications > [App] > Channel Notifications - // CATEGORY: SETTINGS - // OS: N - NOTIFICATION_TOPIC_NOTIFICATION = 265; - - // OPEN: Settings > Security > User credentials - // CATEGORY: Settings - // OS: N - USER_CREDENTIALS = 285; - - // Logs that the user has edited the enabled VR listeners. - // CATEGORY: SETTINGS - // OS: N - VR_MANAGE_LISTENERS = 334; - - // Settings -> Accessibility -> Click after pointer stops moving - // CATEGORY: SETTINGS - // OS: N - ACCESSIBILITY_TOGGLE_AUTOCLICK = 335; - - // Settings -> Sound - // CATEGORY: SETTINGS - // OS: N - SOUND = 336; - - // Settings -> Notifications -> Gear - // CATEGORY: SETTINGS - // OS: N - CONFIGURE_NOTIFICATION = 337; - - // Settings -> Wi-Fi -> Gear - // CATEGORY: SETTINGS - // OS: N - CONFIGURE_WIFI = 338; - - // Settings -> Display -> Display size - // OS: N - DISPLAY_SCREEN_ZOOM = 339; - - // Settings -> Display -> Font size - // CATEGORY: SETTINGS - // OS: N - ACCESSIBILITY_FONT_SIZE = 340; - - // Settings -> Data usage -> Cellular/Wi-Fi data usage - // CATEGORY: SETTINGS - // OS: N - DATA_USAGE_LIST = 341; - - // Settings -> Data usage -> Billing cycle or DATA_USAGE_LIST -> Gear - // CATEGORY: SETTINGS - // OS: N - BILLING_CYCLE = 342; - - // DATA_USAGE_LIST -> Any item or App info -> Data usage - // CATEGORY: SETTINGS - // OS: N - APP_DATA_USAGE = 343; - - // Settings -> Language & input -> Language - // CATEGORY: SETTINGS - // OS: N - USER_LOCALE_LIST = 344; - - // Settings -> Language & input -> Virtual keyboard - // CATEGORY: SETTINGS - // OS: N - VIRTUAL_KEYBOARDS = 345; - - // Settings -> Language & input -> Physical keyboard - // CATEGORY: SETTINGS - // OS: N - PHYSICAL_KEYBOARDS = 346; - - // Settings -> Language & input -> Virtual keyboard -> Add a virtual keyboard - // CATEGORY: SETTINGS - // OS: N - ENABLE_VIRTUAL_KEYBOARDS = 347; - - // Settings -> Data usage -> Data Saver - // CATEGORY: SETTINGS - // OS: N - DATA_SAVER_SUMMARY = 348; - - // Settings -> Data usage -> Data Saver -> Unrestricted data access - // CATEGORY: SETTINGS - // OS: N - DATA_USAGE_UNRESTRICTED_ACCESS = 349; - - // Settings -> Apps -> Gear -> Special access - SPECIAL_ACCESS = 351; - - // OPEN: SUW Welcome Screen -> Vision Settings - // CATEGORY: SETTINGS - // OS: N - SUW_ACCESSIBILITY = 367; - - // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification gestures (Renamed in O) - // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification -> Magnify with triple-tap - // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification -> Magnify with button - // ACTION: New magnification gesture configuration is chosen - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: N - SUW_ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 368; - - // OPEN: SUW Welcome Screen -> Vision Settings -> Font size - // ACTION: New font size is chosen - // SUBTYPE: 0 is small, 1 is default, 2 is large, 3 is largest - // CATEGORY: SETTINGS - // OS: N - SUW_ACCESSIBILITY_FONT_SIZE = 369; - - // OPEN: SUW Welcome Screen -> Vision Settings -> Display size - // ACTION: New display size is chosen - // SUBTYPE: 0 is small, 1 is default, 2 is large, 3 is larger, 4 is largest - // CATEGORY: SETTINGS - // OS: N - SUW_ACCESSIBILITY_DISPLAY_SIZE = 370; - - // OPEN: SUW Welcome Screen -> Vision Settings -> TalkBack - // ACTION: New screen reader configuration is chosen - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: N - SUW_ACCESSIBILITY_TOGGLE_SCREEN_READER = 371; - - // Airplane mode on - SETTINGS_CONDITION_AIRPLANE_MODE = 377; - // AKA Data saver on - SETTINGS_CONDITION_BACKGROUND_DATA = 378; - // Battery saver on - SETTINGS_CONDITION_BATTERY_SAVER = 379; - // Cellular data off - SETTINGS_CONDITION_CELLULAR_DATA = 380; - // Do not disturb on - SETTINGS_CONDITION_DND = 381; - // Hotspot on - SETTINGS_CONDITION_HOTSPOT = 382; - // Work profile off - SETTINGS_CONDITION_WORK_MODE = 383; - - // Settings > Apps > Gear > Special Access > Premium SMS access - PREMIUM_SMS_ACCESS = 388; - - // OPEN: Settings > Accounts > Work profile settings - // CATEGORY: SETTINGS - ACCOUNTS_WORK_PROFILE_SETTINGS = 401; - - // Settings -> Dev options -> Convert to file encryption - CONVERT_FBE = 402; - - // Settings -> Dev options -> Convert to file encryption -> WIPE AND CONVERT... - CONVERT_FBE_CONFIRM = 403; - - // Settings -> Dev options -> Running services - RUNNING_SERVICES = 404; - - // The dialog shown by 3P intent to change current webview implementation. - WEBVIEW_IMPLEMENTATION = 405; - - // OPEN: Settings > Internal storage > Storage manager - // CATEGORY: SETTINGS - STORAGE_MANAGER_SETTINGS = 458; - - // OPEN: Settings -> Gestures - // CATEGORY: SETTINGS - SETTINGS_GESTURES = 459; - - // OPEN: Settings > Display > Night Light - // CATEGORY: SETTINGS - NIGHT_DISPLAY_SETTINGS = 488; - - // Night Light on - SETTINGS_CONDITION_NIGHT_DISPLAY = 492; - - // OPEN: Settings > Language & input > Personal dictionary (single locale) - USER_DICTIONARY_SETTINGS = 514; - - // OPEN: Settings > Date & time > Select time zone - ZONE_PICKER = 515; - - // OPEN: Settings > Security > Device administrators - DEVICE_ADMIN_SETTINGS = 516; - - // OPEN: Settings > Security > Factory Reset Protection dialog - DIALOG_FRP = 528; - - // OPEN: Settings > Custom list preference with confirmation message - DIALOG_CUSTOM_LIST_CONFIRMATION = 529; - - // OPEN: Settings > APN Editor > Error dialog - DIALOG_APN_EDITOR_ERROR = 530; - - // OPEN: Settings > Users > Edit owner info dialog - DIALOG_OWNER_INFO_SETTINGS = 531; - - // OPEN: Settings > Security > Use one lock dialog - DIALOG_UNIFICATION_CONFIRMATION = 532; - - // OPEN: Settings > Security > User Credential - DIALOG_USER_CREDENTIAL = 533; - - // OPEN: Settings > Accounts > Remove account - DIALOG_REMOVE_USER = 534; - - // OPEN: Settings > Accounts > Confirm auto sync dialog - DIALOG_CONFIRM_AUTO_SYNC_CHANGE = 535; - - // OPEN: Settings > Apps > Dialog for running service details - DIALOG_RUNNIGN_SERVICE = 536; - - // OPEN: Settings > Bluetooth > Rename this device - DIALOG_BLUETOOTH_RENAME = 538; - - // OPEN: Settings > Battery optimization > details for app - DIALOG_HIGH_POWER_DETAILS = 540; - - // OPEN: Settings > Keyboard > Show keyboard layout dialog - DIALOG_KEYBOARD_LAYOUT = 541; - - // OPEN: Settings > WIFI Scan permission dialog - DIALOG_WIFI_SCAN_MODE = 543; - - // OPEN: Settings > Wireless > VPN > Config dialog - DIALOG_LEGACY_VPN_CONFIG = 545; - - // OPEN: Settings > Wireless > VPN > Config dialog for app - DIALOG_VPN_APP_CONFIG = 546; - - // OPEN: Settings > Wireless > VPN > Cannot connect dialog - DIALOG_VPN_CANNOT_CONNECT = 547; - - // OPEN: Settings > Wireless > VPN > Replace existing VPN dialog - DIALOG_VPN_REPLACE_EXISTING = 548; - - // OPEN: Settings > Billing cycle > Edit billing cycle dates dialog - DIALOG_BILLING_CYCLE = 549; - - // OPEN: Settings > Billing cycle > Edit data limit/warning dialog - DIALOG_BILLING_BYTE_LIMIT = 550; - - // OPEN: Settings > Billing cycle > turn on data limit dialog - DIALOG_BILLING_CONFIRM_LIMIT = 551; - - // OPEN: Settings > Service > Turn off notification access dialog - DIALOG_DISABLE_NOTIFICATION_ACCESS = 552; - - // OPEN: Settings > Sound > Use personal sound for work profile dialog - DIALOG_UNIFY_SOUND_SETTINGS = 553; - - // OPEN: Settings > Zen mode > Dialog warning about the zen access privileges being granted. - DIALOG_ZEN_ACCESS_GRANT = 554; - - // OPEN: Settings > Zen mode > Dialog warning about the zen access privileges being revoked. - DIALOG_ZEN_ACCESS_REVOKE = 555; - - // OPEN: Settings > Zen mode > Dialog that picks time for zen mode. - DIALOG_ZEN_TIMEPICKER = 556; - - // OPEN: Settings > Apps > Dialog that informs user to allow service access for app. - DIALOG_SERVICE_ACCESS_WARNING = 557; - - // OPEN: Settings > Apps > Dialog for app actions (such as force stop/clear data) - DIALOG_APP_INFO_ACTION = 558; - - // OPEN: Settings > Storage > Dialog for forgetting a storage device - DIALOG_VOLUME_FORGET = 559; - - // OPEN: Settings > Storage > Dialog for initializing a volume - DIALOG_VOLUME_INIT = 561; - - // OPEN: Settings > Storage > Dialog for unmounting a volume - DIALOG_VOLUME_UNMOUNT = 562; - - // OPEN: Settings > Storage > Dialog for renaming a volume - DIALOG_VOLUME_RENAME = 563; - - // OPEN: Settings > Storage > Dialog for clear cache - DIALOG_STORAGE_CLEAR_CACHE = 564; - - // OPEN: Settings > Storage > Dialog for system info - DIALOG_STORAGE_SYSTEM_INFO = 565; - - // OPEN: Settings > Storage > Dialog for other info - DIALOG_STORAGE_OTHER_INFO = 566; - - // OPEN: Settings > Storage > Dialog for user info - DIALOG_STORAGE_USER_INFO = 567; - // OPEN: Settings > Add fingerprint > Dialog when user touches fingerprint icon. - DIALOG_FINGERPRINT_ICON_TOUCH = 568; - - // OPEN: Settings > Add fingerprint > Error dialog - DIALOG_FINGERPINT_ERROR = 569; - - // OPEN: Settings > Fingerprint > Rename or delete dialog - DIALOG_FINGERPINT_EDIT = 570; - - // OPEN: Settings > Fingerprint > Dialog for deleting last fingerprint - DIALOG_FINGERPINT_DELETE_LAST = 571; - - // OPEN: SUW > Fingerprint > Dialog to confirm skip fingerprint setup entirely. - DIALOG_FINGERPRINT_SKIP_SETUP = 573; - - // OPEN: Settings > Proxy Selector error dialog - DIALOG_PROXY_SELECTOR_ERROR = 574; - - // OPEN: Settings > Wifi > P2P Settings > Disconnect dialog - DIALOG_WIFI_P2P_DISCONNECT = 575; - - // OPEN: Settings > Wifi > P2P Settings > Cancel connection dialog - DIALOG_WIFI_P2P_CANCEL_CONNECT = 576; - - // OPEN: Settings > Wifi > P2P Settings > Rename dialog - DIALOG_WIFI_P2P_RENAME = 577; - - // OPEN: Settings > Wifi > P2P Settings > Forget group dialog - DIALOG_WIFI_P2P_DELETE_GROUP = 578; - - // OPEN: Settings > APN > Restore default dialog - DIALOG_APN_RESTORE_DEFAULT = 579; - - // OPEN: Settings > Encryption interstitial accessibility warning dialog - DIALOG_ENCRYPTION_INTERSTITIAL_ACCESSIBILITY = 581; - - // OPEN: Settings > Acessibility > Enable accessiblity service dialog - DIALOG_ACCESSIBILITY_SERVICE_ENABLE = 583; - - // OPEN: Settings > Acessibility > Disable accessiblity service dialog - DIALOG_ACCESSIBILITY_SERVICE_DISABLE = 584; - - // OPEN: Settings > Account > Remove account dialog - DIALOG_ACCOUNT_SYNC_REMOVE = 585; - - // OPEN: Settings > Account > Remove account failed dialog - DIALOG_ACCOUNT_SYNC_FAILED_REMOVAL = 586; - - // OPEN: Settings > Account > Cannot do onetime sync dialog - DIALOG_ACCOUNT_SYNC_CANNOT_ONETIME_SYNC = 587; - - // OPEN: Settings > Display > Night light > Set start time dialog - DIALOG_NIGHT_DISPLAY_SET_START_TIME = 588; - - // OPEN: Settings > Display > Night light > Set end time dialog - DIALOG_NIGHT_DISPLAY_SET_END_TIME = 589; - - - - // OPEN: Settings > User > Edit info dialog - DIALOG_USER_EDIT = 590; - - // OPEN: Settings > User > Confirm remove dialog - DIALOG_USER_REMOVE = 591; - - // OPEN: Settings > User > Enable calling dialog - DIALOG_USER_ENABLE_CALLING = 592; - - // OPEN: Settings > User > Enable calling and sms dialog - DIALOG_USER_ENABLE_CALLING_AND_SMS = 593; - - // OPEN: Settings > User > Cannot manage device message dialog - DIALOG_USER_CANNOT_MANAGE = 594; - - // OPEN: Settings > User > Add user dialog - DIALOG_USER_ADD = 595; - - // OPEN: Settings > User > Setup user dialog - DIALOG_USER_SETUP = 596; - - // OPEN: Settings > User > Setup profile dialog - DIALOG_USER_SETUP_PROFILE = 597; - - // OPEN: Settings > User > Choose user type dialog - DIALOG_USER_CHOOSE_TYPE = 598; - - // OPEN: Settings > User > Need lockscreen dialog - DIALOG_USER_NEED_LOCKSCREEN = 599; - - // OPEN: Settings > User > Confirm exit guest mode dialog - DIALOG_USER_CONFIRM_EXIT_GUEST = 600; - - // OPEN: Settings > User > Edit user profile dialog - DIALOG_USER_EDIT_PROFILE = 601; - - - // OPEN: Settings > Wifi > Saved AP > Edit dialog - DIALOG_WIFI_SAVED_AP_EDIT = 602; - - // OPEN: Settings > Wifi > Edit AP dialog - DIALOG_WIFI_AP_EDIT = 603; - - // OPEN: Settings > Wifi > Write config to NFC dialog - DIALOG_WIFI_WRITE_NFC = 606; - - // OPEN: Settings > Date > Date picker dialog - DIALOG_DATE_PICKER = 607; - - // OPEN: Settings > Date > Time picker dialog - DIALOG_TIME_PICKER = 608; - - // OPEN: Settings > Wireless > Manage wireless plan dialog - DIALOG_MANAGE_MOBILE_PLAN = 609; - - // OPEN Settings > Bluetooth > Attempt to connect to device that shows dialog - BLUETOOTH_DIALOG_FRAGMENT = 613; - - // OPEN: Settings > Security - // CATEGORY: SETTINGS - // OS: O - ENTERPRISE_PRIVACY_SETTINGS = 628; - - // OPEN: Settings > System - SETTINGS_SYSTEM_CATEGORY = 744; - - // OPEN: Settings > Storage - SETTINGS_STORAGE_CATEGORY = 745; - - // OPEN: Settings > Network & Internet - SETTINGS_NETWORK_CATEGORY = 746; - - // OPEN: Settings > Connected Device - SETTINGS_CONNECTED_DEVICE_CATEGORY = 747; - - // OPEN: Settings > App & Notification - SETTINGS_APP_NOTIF_CATEGORY = 748; - - // OPEN: Settings > System > Language & Region - SETTINGS_LANGUAGE_CATEGORY = 750; - - // OPEN: Settings > System > Input & Gesture > Swipe fingerprint for notifications - SETTINGS_GESTURE_SWIPE_TO_NOTIFICATION = 751; - - // OPEN: Settings > System > Input & Gesture > Double tap power button gesture - SETTINGS_GESTURE_DOUBLE_TAP_POWER = 752; - - // OPEN: Settings > System > Input & Gesture > Pick up gesture - SETTINGS_GESTURE_PICKUP = 753; - - // OPEN: Settings > System > Input & Gesture > Double tap screen gesture - SETTINGS_GESTURE_DOUBLE_TAP_SCREEN = 754; - - // OPEN: Settings > System > Input & Gesture > Double twist gesture - SETTINGS_GESTURE_DOUBLE_TWIST = 755; - - // OPEN: Settings > Apps > Default Apps > Default browser - DEFAULT_BROWSER_PICKER = 785; - // OPEN: Settings > Apps > Default Apps > Default emergency app - DEFAULT_EMERGENCY_APP_PICKER = 786; - - // OPEN: Settings > Apps > Default Apps > Default home - DEFAULT_HOME_PICKER = 787; - - // OPEN: Settings > Apps > Default Apps > Default phone - DEFAULT_PHONE_PICKER = 788; - - // OPEN: Settings > Apps > Default Apps > Default sms - DEFAULT_SMS_PICKER = 789; - - // OPEN: Settings > Apps > Notification > Notification Assistant - DEFAULT_NOTIFICATION_ASSISTANT = 790; - - - // OPEN: Settings > Apps > Default Apps > Warning dialog to confirm selection - DEFAULT_APP_PICKER_CONFIRMATION_DIALOG = 791; - - // OPEN: Settings > Apps > Default Apps > Default autofill app - DEFAULT_AUTOFILL_PICKER = 792; - - // OPEN: Settings > Apps > Gear > Special Access > Install other apps - // CATEGORY: SETTINGS - // OS: 8.0 - MANAGE_EXTERNAL_SOURCES = 808; - - // Logs that the user has edited the picture-in-picture settings. - // CATEGORY: SETTINGS - SETTINGS_MANAGE_PICTURE_IN_PICTURE = 812; - - // OPEN: SUW Welcome Screen -> Vision Settings -> Select to Speak - // ACTION: Select to Speak configuration is chosen - // SUBTYPE: 0 is off, 1 is on - // CATEGORY: SETTINGS - // OS: N - SUW_ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK = 817; - - // OPEN: Settings > System > Backup - // CATEGORY: SETTINGS - // OS: O - BACKUP_SETTINGS = 818; - - // OPEN: Settings > Storage > Games - // CATEGORY: SETTINGS - // OS: O - APPLICATIONS_STORAGE_GAMES = 838; - - // OPEN: Settings > Storage > Audio and Music - // CATEGORY: SETTINGS - // OS: O - APPLICATIONS_STORAGE_MUSIC = 839; - - // ACTION: Settings > Storage > Free Up Space to launch Deletion Helper - // CATEGORY: SETTINGS - // OS: O - STORAGE_FREE_UP_SPACE_NOW = 840; - - // ACTION: Settings > Storage > Files to open the File Manager - // CATEGORY: SETTINGS - // OS: O - STORAGE_FILES = 841; - - // OPEN: Settings > Apps > Default Apps > Assist > Default assist - DEFAULT_ASSIST_PICKER = 843; - - // OPEN: Settings > Apps > Default Apps > Assist > Default voice input - DEFAULT_VOICE_INPUT_PICKER = 844; - - // OPEN: Settings > Storage > [Profile] - SETTINGS_STORAGE_PROFILE = 845; - - // OPEN: Settings > Security & screen lock -> Encryption & crendentials - // CATEGORY: SETTINGS - // OS: O - ENCRYPTION_AND_CREDENTIAL = 846; - - // OPEN: Settings > Wi-Fi > Network Details (click on Access Point) - // CATEGORY: SETTINGS - // OS: O - WIFI_NETWORK_DETAILS = 849; - - // OPEN: Settings > Wi-Fi > Wifi Preferences -> Advanced -> Network Scorer - // CATEGORY: SETTINGS - // OS: O - SETTINGS_NETWORK_SCORER = 861; - - // OPEN: Settings > About device > Model > Hardware info dialog - DIALOG_SETTINGS_HARDWARE_INFO = 862; - - // OPEN: Settings > Security & screen lock -> Lock screen preferences - // CATEGORY: SETTINGS - SETTINGS_LOCK_SCREEN_PREFERENCES = 882; - - - // OPEN: Settings -> Display -> When in VR Mode - VR_DISPLAY_PREFERENCE = 921; - - // OPEN: Settings > Accessibility > Magnification - // CATEGORY: SETTINGS - // OS: O - ACCESSIBILITY_SCREEN_MAGNIFICATION_SETTINGS = 922; - - // OPEN: Settings -> System -> Reset options - RESET_DASHBOARD = 924; - - // OPEN: Settings > Security > Nexus Imprint > [Fingerprint] > Delete - // CATEGORY: SETTINGS - // OS: O - FINGERPRINT_REMOVE_SIDECAR = 934; - - // OPEN: Settings > Storage > Movies & TV - // CATEGORY: SETTINGS - // OS: O - APPLICATIONS_STORAGE_MOVIES = 935; - - // OPEN: Settings > Security > Managed Device Info > Apps installed - // CATEGORY: SETTINGS - // OS: O - ENTERPRISE_PRIVACY_INSTALLED_APPS = 938; - - // OPEN: Settings > Security > Managed Device Info > nnn permissions - // CATEGORY: SETTINGS - // OS: O - ENTERPRISE_PRIVACY_PERMISSIONS = 939; - - - // OPEN: Settings > Security > Managed Device Info > Default apps - // CATEGORY: SETTINGS - // OS: O - ENTERPRISE_PRIVACY_DEFAULT_APPS = 940; - - // OPEN: Choose screen lock dialog in Settings - // CATEGORY: SETTINGS - // OS: O DR - SETTINGS_CHOOSE_LOCK_DIALOG = 990; - - // OPEN: Settings > System > Languages & input > Assist gesture - // CATEGORY: SETTINGS - // OS: O DR - SETTINGS_ASSIST_GESTURE = 996; - - // OPEN: Settings > Connected Devices > Bluetooth > (click on details link for a paired device) - BLUETOOTH_DEVICE_DETAILS = 1009; - - // OPEN: Settings > credential pages - prompt for key guard configuration confirmation - CONFIGURE_KEYGUARD_DIALOG = 1010; - - // OPEN: Settings > Network > Tether > Wi-Fi hotspot - WIFI_TETHER_SETTINGS = 1014; - - // OPEN: Settings->Connected Devices->Bluetooth->(click on details link for a paired device) - // -> Edit name button. - // CATEGORY: SETTINGS - // OS: O DR - DIALOG_BLUETOOTH_PAIRED_DEVICE_RENAME = 1015; - - // OPEN: Settings > Connected devices > Bluetooth > Pair new device - // CATEGORY: SETTINGS - // OS: O DR - BLUETOOTH_PAIRING = 1018; - - // OPEN: Settings->Connected Devices->Bluetooth->(click on details link for a paired device) - // -> Forget button. - // CATEGORY: SETTINGS - // OS: O DR - DIALOG_BLUETOOTH_PAIRED_DEVICE_FORGET = 1031; - - // OPEN: Settings > Storage > Photos & Videos - // CATEGORY: SETTINGS - // OS: O MR - APPLICATIONS_STORAGE_PHOTOS = 1092; - - // OPEN: Settings > Display > Colors - // CATEGORY: SETTINGS - // OS: O MR - COLOR_MODE_SETTINGS = 1143; - - // OPEN: Settings > Developer Options > Experiment dashboard - // CATEGORY: SETTINGS - SETTINGS_FEATURE_FLAGS_DASHBOARD = 1217; - - // OPEN: Settings > Notifications > [App] > Topic Notifications - // CATEGORY: SETTINGS - // OS: P - NOTIFICATION_CHANNEL_GROUP = 1218; - - // OPEN: Settings > Developer options > Enable > Info dialog - // CATEGORY: SETTINGS - // OS: P - DIALOG_ENABLE_DEVELOPMENT_OPTIONS = 1219; - - // OPEN: Settings > Developer options > OEM unlocking > Info dialog - // CATEGORY: SETTINGS - // OS: P - DIALOG_ENABLE_OEM_UNLOCKING = 1220; - - // OPEN: Settings > Developer options > USB debugging > Info dialog - // CATEGORY: SETTINGS - // OS: P - DIALOG_ENABLE_ADB = 1222; - - // OPEN: Settings > Security > Nexus Imprint > [Fingerprint] - // CATEGORY: SETTINGS - // OS: P - FINGERPRINT_AUTHENTICATE_SIDECAR = 1221; - - // OPEN: Settings > Developer options > Revoke USB debugging authorizations > Info dialog - // CATEGORY: SETTINGS - // OS: P - DIALOG_CLEAR_ADB_KEYS = 1223; - - // Open: Settings > Developer options > Quick setting tile config - // CATEGORY: SETTINGS - // OS: P - DEVELOPMENT_QS_TILE_CONFIG = 1224; - - // OPEN: Settings > Developer options > Store logger data persistently on device > Info dialog - // CATEGORY: SETTINGS - // OS: P - DIALOG_LOG_PERSIST = 1225; - - // OPEN: Settings > Network & Internet > Mobile network > Wi-Fi calling - // CATEGORY: SETTINGS - // OS: P - WIFI_CALLING_FOR_SUB = 1230; - - // Open: Settings > Dev options > Oem unlock > lock it > warning dialog. - // OS: P - DIALOG_OEM_LOCK_INFO = 1238; - - // Open: Settings > System > About phone > IMEI - // CATEGORY: SETTINGS - // OS: P - DIALOG_IMEI_INFO = 1240; - - // OPEN: Settings > System > About Phone > Sim status - // CATEGORY: SETTINGS - // OS: P - DIALOG_SIM_STATUS = 1246; - - // OPEN: Settings > System > About Phone > Android Version - // CATEGORY: SETTINGS - // OS: P - DIALOG_FIRMWARE_VERSION = 1247; - - // OPEN: Settings > Battery(version 2) - // CATEGORY: SETTINGS - // OS: P - FUELGAUGE_POWER_USAGE_SUMMARY_V2 = 1263; - - // OPEN: Settings > Connected devices > Connection preferences - // CATEGORY: SETTINGS - // OS: P - CONNECTION_DEVICE_ADVANCED = 1264; - - // OPEN: Settings > Security > Screen lock gear icon - // CATEGORY: SETTINGS - // OS: P - SCREEN_LOCK_SETTINGS = 1265; - - // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Delete rule (trash can icon) - // CATEGORY: SETTINGS - // OS: P - NOTIFICATION_ZEN_MODE_DELETE_RULE_DIALOG = 1266; - - // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Add rule > Event/Time - // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Select rule ("Event") > Rule name - // CATEGORY: SETTINGS - // OS: P - NOTIFICATION_ZEN_MODE_RULE_NAME_DIALOG = 1269; - - // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Add rule - // CATEGORY: SETTINGS - // OS: P - NOTIFICATION_ZEN_MODE_RULE_SELECTION_DIALOG = 1270; - - // OPEN: Settings > Battery > Smart Battery - // CATEGORY: SETTINGS - // OS: P - FUELGAUGE_SMART_BATTERY = 1281; - - // OPEN: Settings > Battery > Smart Battery > Restricted apps - // CATEGORY: SETTINGS - // OS: P - FUELGAUGE_RESTRICTED_APP_DETAILS = 1285; - - // OPEN: Settings > Sound & notification > Do Not Disturb > Turn on now - // CATEGORY: SETTINGS - // OS: P - NOTIFICATION_ZEN_MODE_ENABLE_DIALOG = 1286; - - // OPEN: Settings->Connected Devices->USB->(click on details link) - // CATEGORY: SETTINGS - // OS: P - USB_DEVICE_DETAILS = 1291; - - // OPEN: Settings > Accessibility > Vibration - // CATEGORY: SETTINGS - // OS: P - ACCESSIBILITY_VIBRATION = 1292; - - // OPEN: Settings > Accessibility > Vibration > Notification vibration - // CATEGORY: SETTINGS - // OS: P - ACCESSIBILITY_VIBRATION_NOTIFICATION = 1293; - - // OPEN: Settings > Accessibility > Vibration > Touch vibration - // CATEGORY: SETTINGS - // OS: P - ACCESSIBILITY_VIBRATION_TOUCH = 1294; - - // OPEN: Settings->Developer Options->Default USB - // CATEGORY: SETTINGS - // OS: P - USB_DEFAULT = 1312; - - // OPEN: Settings > Battery > Battery tip > Battery tip Dialog - // CATEGORY: SETTINGS - // OS: P - FUELGAUGE_BATTERY_TIP_DIALOG = 1323; - - // OPEN: DND Settings > What to block - // OS: P - ZEN_WHAT_TO_BLOCK = 1339; - - // OPEN: Settings > Sounds > Do Not Disturb > Duration - // CATEGORY: SETTINGS - // OS: P - NOTIFICATION_ZEN_MODE_DURATION_DIALOG = 1341; - - // OPEN: Settings > Date & time > Select time zone -> Region - // CATEGORY: SETTINGS - // OS: P - SETTINGS_ZONE_PICKER_REGION = 1355; - - // OPEN: Settings > Date & time > Select time zone -> Time Zone - // CATEGORY: SETTINGS - // OS: P - SETTINGS_ZONE_PICKER_TIME_ZONE = 1356; - // OPEN: Settings > Date & time > Select time zone -> Select UTC Offset - // CATEGORY: SETTINGS - // OS: P - SETTINGS_ZONE_PICKER_FIXED_OFFSET = 1357; - - // OPEN: Settings > Gestures > Prevent Ringing - // OS: P - SETTINGS_PREVENT_RINGING = 1360; - - // Settings > Condition > Device muted - // CATEGORY: SETTINGS - // OS: P - SETTINGS_CONDITION_DEVICE_MUTED = 1368; - - // Settings > Condition > Device vibrate - // CATEGORY: SETTINGS - // OS: P - SETTINGS_CONDITION_DEVICE_VIBRATE = 1369; - - // OPEN: Settings > Connected devices > previously connected devices - // CATEGORY: SETTINGS - // OS: P - PREVIOUSLY_CONNECTED_DEVICES = 1370; - - // OPEN: Settings > Network & Internet > Wi-Fi > Wi-Fi Preferences > Turn on Wi-Fi automatically - // note: Wifi Scanning must be off for this dialog to show - // CATEGORY: SETTINGS - // OS: P - WIFI_SCANNING_NEEDED_DIALOG = 1373; - - // OPEN: Settings > System > Gestures > System navigation - // CATEGORY: SETTINGS - // OS: P - SETTINGS_GESTURE_SWIPE_UP = 1374; - - // OPEN: Settings > Storage > Dialog to format a storage volume - // CATEGORY: SETTINGS - // OS: P - DIALOG_VOLUME_FORMAT = 1375; - - // OPEN: DND onboarding activity - // CATEGORY: SETTINGS - // OS: P - SETTINGS_ZEN_ONBOARDING = 1380; - - // OPEN: Settings > Display > Auto brightness - // CATEGORY: SETTINGS - // OS: P - SETTINGS_AUTO_BRIGHTNESS = 1381; - - // OPEN: Settings > Connected Devices > Bluetooth - // CATEGORY: SETTINGS - // OS: P - BLUETOOTH_FRAGMENT = 1390; - - // Screen: DND Settings > Notifications - // OS: P - SETTINGS_ZEN_NOTIFICATIONS = 1400; - - // An event category for slices. - // OPEN: Slice became visible. - // CLOSE: Slice became invisible. - // ACTION: Slice was tapped. - SLICE = 1401; - - // OPEN: Settings -> Developer Options -> Disable Bluetooth A2DP hardware - // offload - // CATEGORY: SETTINGS - // OS: P - DIALOG_BLUETOOTH_DISABLE_A2DP_HW_OFFLOAD = 1441; - - // OPEN: Settings homepage - SETTINGS_HOMEPAGE = 1502; - - // OPEN: Settings > Create shortcut(widget) - // CATEGORY: SETTINGS - // OS: Q - SETTINGS_CREATE_SHORTCUT = 1503; - - // OPEN: Face Enroll introduction - // CATEGORY: SETTINGS - // OS: Q - FACE_ENROLL_INTRO = 1506; - - // OPEN: Face Enroll introduction - // CATEGORY: SETTINGS - // OS: Q - FACE_ENROLL_ENROLLING = 1507; - - // OPEN: Face Enroll introduction - // CATEGORY: SETTINGS - // OS: Q - FACE_ENROLL_FINISHED = 1508; - - // OPEN: Face Enroll sidecar - // CATEGORY: SETTINGS - // OS: Q - FACE_ENROLL_SIDECAR = 1509; - - // OPEN: Settings > Add face > Error dialog - // OS: Q - DIALOG_FACE_ERROR = 1510; - - // OPEN: Settings > Security > Face - // CATEGORY: SETTINGS - // OS: Q - FACE = 1511; - - // OPEN: Settings > Acessibility > HearingAid pairing instructions dialog - // CATEGORY: SETTINGS - // OS: Q - DIALOG_ACCESSIBILITY_HEARINGAID = 1512; - - // OPEN: Settings > Add face - // OS: Q - FACE_ENROLL_PREVIEW = 1554; - - // OPEN: Settings > Network & Internet > Wi-Fi > Add network - // CATEGORY: SETTINGS - // OS: Q - SETTINGS_WIFI_ADD_NETWORK = 1556; - - // OPEN: Settings > System > Input & Gesture > Reach up gesture - // OS: Q - SETTINGS_GESTURE_WAKE_LOCK_SCREEN = 1557; - - // OPEN: Settings > System > Input & Gesture > Wake screen - SETTINGS_GESTURE_WAKE_SCREEN = 1570; - - // OPEN: Settings > Network & internet > Mobile network - MOBILE_NETWORK = 1571; - - // OPEN: Settings > Network & internet > Mobile network > Choose network - MOBILE_NETWORK_SELECT = 1581; - - // OPEN: Settings > Network & internet > Mobile network > Mobile Data > Dialog - MOBILE_DATA_DIALOG = 1582; - - // OPEN: Settings > Network & internet > Mobile network > Data roaming > Dialog - MOBILE_ROAMING_DIALOG = 1583; - - // Settings > Display > Lock screen display > On lock screen - LOCK_SCREEN_NOTIFICATION_CONTENT = 1584; - - // ConfirmDeviceCredentials > BiometricPrompt - BIOMETRIC_FRAGMENT = 1585; - - // OPEN: Biometric Enrollment (android.settings.BIOMETRIC_ENROLL action intent) - BIOMETRIC_ENROLL_ACTIVITY = 1586; - - // OPEN: Settings > Privacy - TOP_LEVEL_PRIVACY = 1587; - - // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions > - // Allow apps to override - // CATEGORY: SETTINGS - // OS: Q - NOTIFICATION_ZEN_MODE_OVERRIDING_APPS = 1588; - - - // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions > - // Allow apps to override > Choose app - // CATEGORY: SETTINGS - // OS: Q - NOTIFICATION_ZEN_MODE_OVERRIDING_APP = 1589; - - // OPEN: Settings > Developer options > Disable > Info dialog - DIALOG_DISABLE_DEVELOPMENT_OPTIONS = 1591; - - // OPEN: WifiDppConfiguratorActivity (android.settings.WIFI_DPP_CONFIGURATOR_XXX action intents) - SETTINGS_WIFI_DPP_CONFIGURATOR = 1595; - - // OPEN: WifiDppEnrolleeActivity (android.settings.WIFI_DPP_ENROLLEE_XXX action intents) - SETTINGS_WIFI_DPP_ENROLLEE = 1596; - - // OPEN: Settings > Apps & Notifications -> Special app access -> Financial Apps Sms Access - SETTINGS_FINANCIAL_APPS_SMS_ACCESS = 1597; - - - - // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) - // > Do Not Disturb behavior - // CATEGORY: SETTINGS - // OS: Q - ZEN_CUSTOM_RULE_SETTINGS = 1604; - - // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) - // > Do Not Disturb behavior > Custom - // CATEGORY: SETTINGS - // OS: Q - ZEN_CUSTOM_RULE_SOUND_SETTINGS = 1605; - - // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) - // > Do Not Disturb behavior > Use default Do Not Disturb behavior - // CATEGORY: SETTINGS - // OS: Q - ZEN_CUSTOM_RULE_DEFAULT_SETTINGS = 1606; - - // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) - // > Do Not Disturb behavior > Use default Do Not Disturb behavior - // > Notification restriction - // CATEGORY: SETTINGS - // OS: Q - ZEN_CUSTOM_RULE_NOTIFICATION_RESTRICTIONS = 1608; - - // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) - // > Do Not Disturb behavior > Use default Do Not Disturb behavior - // > Notification restriction > Custom - // CATEGORY: SETTINGS - // OS: Q - ZEN_CUSTOM_RULE_VIS_EFFECTS = 1609; - - // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) - // > Do Not Disturb behavior > Use default Do Not Disturb behavior - // > Notification restriction > Custom > Allow messages - // CATEGORY: SETTINGS - // OS: Q - ZEN_CUSTOM_RULE_MESSAGES = 1610; - - // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) - // > Do Not Disturb behavior > Use default Do Not Disturb behavior - // > Notification restriction > Custom > Allow calls - // CATEGORY: SETTINGS - // OS: Q - ZEN_CUSTOM_RULE_CALLS = 1611; - - // OPEN: Settings > Sound > Do Not Disturb > Click footer link if custom settings applied - // CATEGORY: SETTINGS - // OS: Q - ZEN_CUSTOM_SETTINGS_DIALOG = 1612; - - // OPEN: Settings > Developer Options > Graphics Driver Preferences - // CATEGORY: SETTINGS - // OS: Q - SETTINGS_GRAPHICS_DRIVER_DASHBOARD = 1613; - - // OPEN: Settings > Accessibility > Vibration > Ring vibration - // CATEGORY: SETTINGS - // OS: Q - ACCESSIBILITY_VIBRATION_RING = 1620; - - // OPEN: Settings > System > Input & Gesture > Skip songs - SETTINGS_GESTURE_SKIP = 1624; - - // OPEN: Settings > System > Input & Gesture > Silence alerts - SETTINGS_GESTURE_SILENCE = 1625; - - // OPEN: Settings > System > Input & Gesture > Tap to check - SETTINGS_GESTURE_TAP_SCREEN = 1626; - - // OPEN: Settings > Network & internet > Click Mobile network to land on a page with a list of - // SIM/eSIM subscriptions. - MOBILE_NETWORK_LIST = 1627; - - // OPEN: Settings > Display > Adaptive sleep - // OS: Q - SETTINGS_ADAPTIVE_SLEEP = 1628; - - // OPEN: Settings > System > Aware - SETTINGS_AWARE = 1632; - - // OPEN: Settings > System > Aware > Disable > Dialog - DIALOG_AWARE_DISABLE = 1633; - - // OPEN: Settings > Settings > Network & internet > Click Mobile network to land on page with - // details for a SIM/eSIM mobile network > Click edit icon to bring up a rename dialog. - // OS: Q - MOBILE_NETWORK_RENAME_DIALOG = 1642; - - // OPEN: Set new password (android.app.action.SET_NEW_PASSWORD action intent) - // CATEGORY: SETTINGS - // OS: Q - SET_NEW_PASSWORD_ACTIVITY = 1644; - - // Panel for Internet Connectivity - PANEL_INTERNET_CONNECTIVITY = 1654; - - // Panel for Volume - PANEL_VOLUME = 1655; - - // Panel for NFC - PANEL_NFC = 1656; - - // Panel for Media Output - PANEL_MEDIA_OUTPUT = 1657; - - // Mapping: go/at-mapping - PAGE_ATSSI = 1667; - - PAGE_ATSII = 1668; - - PAGE_ATUS = 1669; - - PAGE_ATSSP = 1670; - - PAGE_ATSAP = 1671; - - PAGE_ATSCP = 1672; - - PAGE_ATHNP = 1673; - - // OPEN: Accessibility detail settings (android.settings.ACCESSIBILITY_DETAILS_SETTINGS intent) - ACCESSIBILITY_DETAILS_SETTINGS = 1682; - - // Open: Settings will show the conditional when Grayscale mode is on - SETTINGS_CONDITION_GRAYSCALE_MODE = 1683; - - // Panel for Wifi - PANEL_WIFI = 1687; - - // Open: Settings > Special App Access > Do not disturb control for app - ZEN_ACCESS_DETAIL = 1692; - - // OPEN: Settings > Face > Remove face - // OS: Q - DIALOG_FACE_REMOVE = 1693; - - // Settings > Display > Theme - DARK_UI_SETTINGS = 1698; - - // Settings > global bubble settings - BUBBLE_SETTINGS = 1699; - - // Settings > app > bubble settings - APP_BUBBLE_SETTINGS = 1700; - - // OPEN: Settings > System > Aware > Info dialog - DIALOG_AWARE_STATUS = 1701; - - // Open: Settings > app > bubble settings > confirmation dialog - DIALOG_APP_BUBBLE_SETTINGS = 1702; - - // OPEN: Settings > Pick SIM dialog - DIALOG_SIM_LIST = 1707; - - // OPEN: Settings > Pick SIM (that supports calling) dialog - DIALOG_CALL_SIM_LIST = 1708; - - // OPEN: Settings > Pick preferred SIM dialog - DIALOG_PREFERRED_SIM_PICKER = 1709; - - // OPEN: Settings > Network & internet > Mobile network > Delete sim - DIALOG_DELETE_SIM_CONFIRMATION = 1713; - - // OPEN: Settings > Network & internet > Mobile network > Delete sim > (answer yes to - // confirmation) - DIALOG_DELETE_SIM_PROGRESS = 1714; - - // Settings > Apps and notifications > Notifications > Gentle notifications - GENTLE_NOTIFICATIONS_SCREEN = 1715; - - // OPEN: Settings > System > Gestures > Global Actions Panel - // CATEGORY: SETTINGS - // OS: Q - GLOBAL_ACTIONS_PANEL_SETTINGS = 1728; - - // OPEN: Settings > Display > Dark Theme - // CATEGORY: SETTINGS - // OS: Q - // Note: Only shows up on first time toggle - DIALOG_DARK_UI_INFO = 1740; - - // OPEN: Settings > About phone > Legal information > Google Play system update licenses - // CATEGORY: SETTINGS - // OS: Q - MODULE_LICENSES_DASHBOARD = 1746; - - // OPEN: Settings > System > Gestures > System navigation > Info icon - // CATEGORY: SETTINGS - // OS: Q - // Note: Info icon is visible only when gesture navigation is not available and disabled - SETTINGS_GESTURE_NAV_NOT_AVAILABLE_DLG = 1747; - - // OPEN: Settings > System > Gestures > System navigation > Gear icon - // CATEGORY: SETTINGS - // OS: Q - // Note: Gear icon is shown next to gesture navigation preference and opens sensitivity dialog - SETTINGS_GESTURE_NAV_BACK_SENSITIVITY_DLG = 1748; - - // OPEN: Settings > System > Aware > Aware Display - // CATEGORY: SETTINGS - // OS: Q - SETTINGS_AWARE_DISPLAY = 1750; - - // OPEN: Settings > System > Input & Gesture > tap gesture - // CATEGORY: SETTINGS - // OS: Q - SETTINGS_GESTURE_TAP = 1751; - // ---- End Q Constants, all Q constants go above this line ---- - // OPEN: Settings > Network & Internet > Wi-Fi > Click new network - // CATEGORY: SETTINGS - // OS: R - SETTINGS_WIFI_CONFIGURE_NETWORK = 1800; - - // OPEN: Settings > Accessibility > Magnification - // CATEGORY: SETTINGS - // OS: R - // Note: Shows up only when Magnify with shortcut is enabled - // and under accessibility button mode. - DIALOG_TOGGLE_SCREEN_MAGNIFICATION_ACCESSIBILITY_BUTTON = 1801; - - // OPEN: Settings > Accessibility > Magnification - // CATEGORY: SETTINGS - // OS: R - // Note: Shows up only when Magnify with shortcut is enabled. - // and under gesture navigation mode. - DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION = 1802; - - // OPEN: Settings > Security & screen lock -> Encryption & credentials > Install a certificate - // CATEGORY: SETTINGS - // OS: R - INSTALL_CERTIFICATE_FROM_STORAGE = 1803; - - // OPEN: Settings > Apps and notifications > Special app access > notification access > - // an app - // CATEGORY: SETTINGS - // OS: R - NOTIFICATION_ACCESS_DETAIL = 1804; - - // OPEN: Settings > Developer Options > Platform Compat - // CATEGORY: SETTINGS - // OS: R - SETTINGS_PLATFORM_COMPAT_DASHBOARD = 1805; - - // OPEN: Settings > Location -> Work profile tab - // CATEGORY: SETTINGS - // OS: R - LOCATION_WORK = 1806; - - // OPEN: Settings > Account -> Work profile tab - // CATEGORY: SETTINGS - // OS: R - ACCOUNT_WORK = 1807; - - // OPEN: Settings > Developer Options > Bug report handler - // CATEGORY: SETTINGS - // OS: R - SETTINGS_BUGREPORT_HANDLER = 1808; - - // Panel for adding Wi-Fi networks - // CATEGORY: SETTINGS - // OS: R - PANEL_ADD_WIFI_NETWORKS = 1809; - - // OPEN: Settings > Accessibility > Enable the feature or shortcut > Show tutorial dialog - // CATEGORY: SETTINGS - // OS: R - DIALOG_ACCESSIBILITY_TUTORIAL = 1810; - - // OPEN: Settings > Accessibility > Edit shortcut dialog - // CATEGORY: SETTINGS - // OS: R - DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT = 1812; - - // OPEN: Settings > Accessibility > Magnification > Edit shortcut dialog - // CATEGORY: SETTINGS - // OS: R - DIALOG_MAGNIFICATION_EDIT_SHORTCUT = 1813; - - // OPEN: Settings > Accessibility > Color correction > Edit shortcut dialog - // CATEGORY: SETTINGS - // OS: R - DIALOG_DALTONIZER_EDIT_SHORTCUT = 1814; - - // OPEN: Settings > Accessibility > Magnification > Settings - // CATEGORY: SETTINGS - // OS: R - ACCESSIBILITY_MAGNIFICATION_SETTINGS = 1815; - - // OPEN: Settings > Accessibility > Magnification > Settings > Magnification area dialog - // CATEGORY: SETTINGS - // OS: R - DIALOG_MAGNIFICATION_CAPABILITY = 1816; - - // OPEN: Settings > Accessibility > Color inversion - // CATEGORY: SETTINGS - // OS: R - ACCESSIBILITY_COLOR_INVERSION_SETTINGS = 1817; - - // OPEN: Settings > Accessibility > Color inversion > Edit shortcut dialog - // CATEGORY: SETTINGS - // OS: R - DIALOG_COLOR_INVERSION_EDIT_SHORTCUT = 1818; - - // OPEN: Settings > Accessibility > Captions preference > Captions appearance - // CATEGORY: SETTINGS - // OS: R - ACCESSIBILITY_CAPTION_APPEARANCE = 1819; - - // OPEN: Settings > Accessibility > Captions preference > More options - // CATEGORY: SETTINGS - // OS: R - ACCESSIBILITY_CAPTION_MORE_OPTIONS = 1820; - - // OPEN: Settings > Battery > Battery share - // CATEGORY: SETTINGS - // OS: R - FUELGAUGE_BATTERY_SHARE = 1821; - - // OPEN: Settings -> Apps & Notifications -> Special App Access - // CATEGORY: SETTINGS - // OS: R - MANAGE_EXTERNAL_STORAGE = 1822; - - // Open: Settings > DND > People - // OS: R - DND_PEOPLE = 1823; - - // OPEN: Settings > Apps and notifications > App info > one of any app > Open by default - // > Open supported links - // CATEGORY: SETTINGS - // OS: R - OPEN_SUPPORTED_LINKS = 1824; - - // OPEN: Settings > Display > Dark theme > Set start time dialog - DIALOG_DARK_THEME_SET_START_TIME = 1825; - - // OPEN: Settings > Display > Dark theme > Set end time dialog - DIALOG_DARK_THEME_SET_END_TIME = 1826; - - // OPEN: Settings -> Sound -> Vibrate for calls - // CATEGORY: SETTINGS - // OS: R - VIBRATE_FOR_CALLS = 1827; - - // OPEN: Settings > Connected devices > Connection preferences > NFC - // CATEGORY: SETTINGS - // OS: R - CONNECTION_DEVICE_ADVANCED_NFC = 1828; - - // OPEN: Settings -> Apps & Notifications -> Special App Access - INTERACT_ACROSS_PROFILES = 1829; - - // OPEN: Settings > Notifications > (app or conversations) > conversation - NOTIFICATION_CONVERSATION_SETTINGS = 1830; - - // OPEN: Settings > Developer Options > Wireless debugging - // CATEGORY: SETTINGS - // OS: R - SETTINGS_ADB_WIRELESS = 1831; - - // OPEN: Settings > Developer Options > Wireless debugging - // > Pair device with pairing code > Pairing code dialog - // CATEGORY: SETTINGS - // OS: R - ADB_WIRELESS_DEVICE_PAIRING_DIALOG = 1832; - - // OPEN: Settings > Developer Options > Wireless debugging - // > Pair device with QR code > Scan QR code > Pairing device dialog - // CATEGORY: SETTINGS - // OS: R - ADB_WIRELESS_DEVICE_QR_PAIRING_DIALOG = 1833; - - // OPEN: Settings > apps & notifications > notifications > conversations - // CATEGORY: SETTINGS - // OS: R - NOTIFICATION_CONVERSATION_LIST_SETTINGS = 1834; - - // Panel for Media Output Group operation - // CATEGORY: SETTINGS - // OS: R - PANEL_MEDIA_OUTPUT_GROUP = 1835; - - // OPEN: Settings > Developer Options > Wireless debugging - // > Click on paired device - // CATEGORY: SETTINGS - // OS: R - ADB_WIRELESS_DEVICE_DETAILS = 1836; - - // Open: Settings > Sound > Do Not Disturb > People > Conversations - // OS: R - DND_CONVERSATIONS = 1837; - - // Open: Settings > Sound > Do Not Disturb > People > Calls - // OS: R - DND_CALLS = 1838; - - // Open: Settings > Sound > Do Not Disturb > People > Messages - // OS: R - DND_MESSAGES = 1839; - - // Open: Settings > Sound > Do Not Disturb > Apps > <Choose App> - // OS: R - DND_APPS_BYPASSING = 1840; - - // OPEN: Settings > System > Gestures > One-Handed - // CATEGORY: SETTINGS - // OS: R QPR - SETTINGS_ONE_HANDED = 1841; - - // OPEN: Settings > Battery > Advanced battery option - // CATEGORY: SETTINGS - // OS: R - FUELGAUGE_ADVANCED_BATTERY_OPTION = 1842; - - // OPEN: Settings > System > Gestures > Power menu - // CATEGORY: SETTINGS - // OS: R - POWER_MENU_SETTINGS = 1843; - - // OPEN: Settings > System > Gestures > Power menu > Device controls - // CATEGORY: SETTINGS - // OS: R - DEVICE_CONTROLS_SETTINGS = 1844; - - // OPEN: Settings > Sound > Media - // CATEGORY: SETTINGS - // OS: R - MEDIA_CONTROLS_SETTINGS = 1845; - - // OPEN: Settings > System > Gestures > Swipe for notification - // CATEGORY: SETTINGS - // OS: R QPR - SETTINGS_SWIPE_BOTTOM_TO_NOTIFICATION = 1846; - - // OPEN: Settings > System > Gestures > Emergency SOS Gesture - // CATEGORY: SETTINGS - // OS: S - EMERGENCY_SOS_GESTURE_SETTINGS = 1847; - - // OPEN: Settings > System > Gestures > Double tap - // CATEGORY: SETTINGS - // OS: S - SETTINGS_COLUMBUS = 1848; - - // OPEN: Settings > Accessibility > Magnification > Settings > Magnification area > Magnification switch shortcut dialog - // CATEGORY: SETTINGS - // OS: S - DIALOG_MAGNIFICATION_SWITCH_SHORTCUT = 1849; - - // OPEN: Settings > Network & internet > Adaptive connectivity - // CATEGORY: SETTINGS - // OS: R QPR - ADAPTIVE_CONNECTIVITY_CATEGORY = 1850; - - // OS: R QPR2 - BLUETOOTH_PAIRING_RECEIVER = 1851; - - // OPEN: Settings > Display > Screen timeout - // CATEGORY: SETTINGS - // OS: S - SCREEN_TIMEOUT = 1852; - - // OPEN: Settings > Accessibility > Reduce Bright Colors - // CATEGORY: SETTINGS - // OS: S - REDUCE_BRIGHT_COLORS_SETTINGS = 1853; - - // OPEN: Settings > Location > Time Zone Detection - // CATEGORY: SETTINGS - // OS: S - LOCATION_TIME_ZONE_DETECTION = 1854; - - // OPEN: Settings > Developer options > Media transcode settings - // CATEGORY: SETTINGS - // OS: S - TRANSCODE_SETTINGS = 1855; -} diff --git a/core/proto/android/app/tvsettings_enums.proto b/core/proto/android/app/tvsettings_enums.proto deleted file mode 100644 index 77bf98f1c15e..000000000000 --- a/core/proto/android/app/tvsettings_enums.proto +++ /dev/null @@ -1,1132 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.app.tvsettings; -option java_multiple_files = true; -option java_outer_classname = "TvSettingsEnums"; - -/** The performed action types */ -enum Action { - - /** - * Denotes an unknown action. It is a filler that should generally be - * avoided. - */ - ACTION_UNKNOWN = 0; - - /** - * Denotes that a TvSettings page is being focused. (Previewing a page in - * two panel settings should NOT be considered as focusing on the page.) - */ - PAGE_FOCUSED = 1; - - /** - * Denotes that an entry (typically a leaf node of settings tree) is - * selected by a user. - */ - ENTRY_SELECTED = 2; - - /** Denotes that a toggle is clicked by a user. */ - TOGGLE_INTERACTED = 3; - - /** - * Denotes that a TvSettings page is being focused in the forward direction - * into the settings tree. - */ - PAGE_FOCUSED_FORWARD = 4; - - /** - * Denotes that a TvSettings page is being focused in the backward direction - * up the settings tree. - */ - PAGE_FOCUSED_BACKWARD = 5; - - /** Denotes that a toggle is turned on by a user. */ - TOGGLED_ON = 6; - - /** Denotes that a toggle is turned off by a user. */ - TOGGLED_OFF = 7; - -} - -/** - * Ids for TvSettings focusable pages or actionable entries - * - * For details of the scheme, please refer to the "Definition of item_id" and - * "Evolve of item_id" sections in go/atv-settings-ww-logging-design. - */ -enum ItemId { - - option allow_alias = true; - - // Filler that should be avoided - UNKNOWN = 0x00000000; - - // TvSettings - TV_SETTINGS_ROOT = 0x00000001; - - // TvSettings unknown/default classic page - PAGE_CLASSIC_DEFAULT = 0x00000002; - - // TvSettings unknown/default slice page - PAGE_SLICE_DEFAULT = 0x00000003; - - // TvSettings unknown/default entry - ENTRY_DEFAULT = 0x00000004; - - // TvSettings > Suggested settings entry - SUGGESTED_SETTINGS = 0x00000010; - - // TvSettings > Quick Settings - QUICK_SETTINGS = 0x00000011; - - // VERSION 1: Starting with Q - // These are ordered in depth-first search manner. - - // TvSettings > Network & Internet - NETWORK = 0x11000000; - - // TvSettings > Network & Internet > Wi-Fi (toggle) - NETWORK_WIFI_ON_OFF = 0x11100000; - - // TvSettings > Network & Internet > - // [A connected network entry in available networks list] - NETWORK_AP_INFO = 0x11200000; - - // TvSettings > Network & Internet > - // [A connected network entry in available networks list] > Proxy settings - NETWORK_AP_INFO_PROXY_SETTINGS = 0x11210000; - - // TvSettings > Network & Internet > - // [A connected network entry in available networks list] > IP settings - NETWORK_AP_INFO_IP_SETTINGS = 0x11220000; - - // TvSettings > Network & Internet > - // [A connected network entry in available networks list] > Forget network - NETWORK_AP_INFO_FORGET_NETWORK = 0x11230000; - - // TvSettings > Network & Internet > - // [A not connected network entry in available networks list] - NETWORK_NOT_CONNECTED_AP = 0x11300000; - - // TvSettings > Network & Internet > See all - NETWORK_SEE_ALL = 0x11400000; - - // TvSettings > Network & Internet > See fewer - NETWORK_SEE_FEWER = 0x11500000; - - // TvSettings > Network & Internet > Add new network - NETWORK_ADD_NEW_NETWORK = 0x11600000; - - // TvSettings > Network & Internet > Scanning always available (toggle) - NETWORK_ALWAYS_SCANNING_NETWORKS = 0x11700000; - - // TvSettings > Network & Internet > Proxy settings (in Ethernet category) - NETWORK_ETHERNET_PROXY_SETTINGS = 0x11800000; - - // TvSettings > Network & Internet > IP settings (in Ethernet category) - NETWORK_ETHERNET_IP_SETTINGS = 0x11900000; - - // TvSettings > Account & Sign In (Slice) - ACCOUNT_SLICE = 0x12000000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] - ACCOUNT_SLICE_REG_ACCOUNT = 0x12100000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Services - ACCOUNT_SLICE_REG_ACCOUNT_SERVICES = 0x12110000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Payment & Purchases - ACCOUNT_SLICE_REG_ACCOUNT_PAYMENT = 0x12120000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Payment & Purchases > - // Require authentication for purchases (reauth interval) - ACCOUNT_SLICE_REG_ACCOUNT_PAYMENT_REAUTH = 0x12121000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Payment & Purchases > - // Require authentication for purchases (reauth interval) > Always - ACCOUNT_SLICE_REG_ACCOUNT_PAYMENT_REAUTH_ALWAYS = 0x12121100; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Payment & Purchases > - // Require authentication for purchases (reauth interval) > Every 30 minutes - ACCOUNT_SLICE_REG_ACCOUNT_PAYMENT_REAUTH_30MINS = 0x12121200; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Payment & Purchases > - // Require authentication for purchases (reauth interval) > Never - ACCOUNT_SLICE_REG_ACCOUNT_PAYMENT_REAUTH_NEVER = 0x12121300; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Google Assistant - ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT = 0x12130000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Google Assistant > SafeSearch filter (toggle) - ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_SAFE_SEARCH = 0x12131000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Google Assistant > Block offensive words (toggle) - ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_BLOCK_OFFENSIVE = 0x12132000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Google Assistant > Searchable apps - ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_SEARCHABLE_APPS = 0x12133000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Google Assistant > Personal results (toggle) - ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_PERSONAL_RESULTS = 0x12134000; - - // TvSettings > Account & Sign In (Slice) > [A regular account] > - // Apps only mode (toggle) - ACCOUNT_SLICE_REG_ACCOUNT_APPS_ONLY_MODE = 0x12140000; - - // Reserving [0x12150000, 0x12190000] for possible future settings - - // TvSettings > Account & Sign In (Slice) > [A regular account] > Remove - ACCOUNT_SLICE_REG_ACCOUNT_REMOVE = 0x121A0000; - - // Reserving [0x12200000, 0x12900000] for possible future settings - - // TvSettings > Account & Sign In (Slice) > Add account... - ACCOUNT_SLICE_ADD_ACCOUNT = 0x12A00000; - - // TvSettings > Account & Sign In (Classic) - ACCOUNT_CLASSIC = 0x13000000; - - // TvSettings > Account & Sign In (Classic) > [A regular account] - ACCOUNT_CLASSIC_REG_ACCOUNT = 0x13100000; - - // TvSettings > Account & Sign In (Classic) > [A regular account] > Sync now - ACCOUNT_CLASSIC_REG_ACCOUNT_SYNC_NOW = 0x13110000; - - // TvSettings > Account & Sign In (Classic) > [A regular account] > - // Remove account - ACCOUNT_CLASSIC_REG_ACCOUNT_REMOVE_ACCOUNT = 0x13120000; - - // TvSettings > Account & Sign In (Classic) > [A regular account] > - // [Choose synced apps] Calendar (toggle) - ACCOUNT_CLASSIC_REG_ACCOUNT_SYNC_CALENDAR = 0x13130000; - - // TvSettings > Account & Sign In (Classic) > [A regular account] > - // [Choose synced apps] Contacts (toggle) - ACCOUNT_CLASSIC_REG_ACCOUNT_SYNC_CONTACTS = 0x13140000; - - // TvSettings > Account & Sign In (Classic) > [A regular account] > - // [Choose synced apps] Google Play Movies & TV (toggle) - ACCOUNT_CLASSIC_REG_ACCOUNT_SYNC_GPMT = 0x13150000; - - // TvSettings > Account & Sign In (Classic) > [A regular account] > - // [Choose synced apps] Google Play Music (toggle) - ACCOUNT_CLASSIC_REG_ACCOUNT_SYNC_GPM = 0x13160000; - - // TvSettings > Account & Sign In (Classic) > [A regular account] > - // [Choose synced apps] People details (toggle) - ACCOUNT_CLASSIC_REG_ACCOUNT_SYNC_PEOPLE = 0x13170000; - - // Reserving [0x13200000, 0x13900000] for possible future settings - - // TvSettings > Account & Sign In (Classic) > Add account - ACCOUNT_CLASSIC_ADD_ACCOUNT = 0x13A00000; - - // TvSettings > Privacy - PRIVACY = 0x14000000; - - // TvSettings > Privacy > Location - PRIVACY_LOCATION = 0x14100000; - - // TvSettings > Privacy > Location > Location status (radio button) - PRIVACY_LOCATION_STATUS = 0x14110000; - - // TvSettings > Privacy > Location > Location status (radio button) > - // Use Wi-Fi to estimate location - PRIVACY_LOCATION_STATUS_USE_WIFI = 0x14111000; - - // TvSettings > Privacy > Location > Location status (radio button) > Off - PRIVACY_LOCATION_STATUS_OFF = 0x14112000; - - // TvSettings > Privacy > Location > Scanning always available (toggle) - PRIVACY_LOCATION_ALWAYS_SCANNING_NETWORKS = 0x14120000; - - // TvSettings > Privacy > Location > [An app that had recent requests] - PRIVACY_LOCATION_REQUESTED_APP = 0x14130000; - - // TvSettings > Privacy > Usage & Diagnostics - PRIVACY_DIAGNOSTICS = 0x14200000; - - // TvSettings > Privacy > Usage & Diagnostics > On (Toggle) - PRIVACY_DIAGNOSTICS_ON_OFF = 0x14210000; - - // TvSettings > Privacy > Ads - PRIVACY_ADS = 0x14300000; - - // The following three IDs may not actually be logged as they are within a - // GMSCore Activity but we reserve IDs for them. - // TvSettings > Privacy > Ads > Reset advertising ID - PRIVACY_ADS_RESET_AD_ID = 0x14310000; - - // TvSettings > Privacy > Ads > Opt out of Ads Personalization - PRIVACY_ADS_OPT_OUT_PERSONALIZATION = 0x14320000; - - // TvSettings > Privacy > Ads > Ads by Google (WebView) - PRIVACY_ADS_ADS_BY_GOOGLE = 0x14330000; - - // TvSettings > Display & Sound - DISPLAY_SOUND = 0x15000000; - - // TvSettings > Display & Sound > Advanced display settings - DISPLAY_SOUND_ADVANCED_DISPLAY = 0x15100000; - - // TvSettings > Display & Sound > Advanced display settings > - // Allow game mode (toggle) - DISPLAY_SOUND_ADVANCED_DISPLAY_GAME_MODE = 0x15110000; - - // TvSettings > Display & Sound > System sounds (toggle) - DISPLAY_SOUND_SYSTEM_SOUNDS = 0x15200000; - - // TvSettings > Display & Sound > Advanced sound settings - DISPLAY_SOUND_ADVANCED_SOUNDS = 0x15300000; - - // TvSettings > Display & Sound > Advanced sound settings > Select formats - DISPLAY_SOUND_ADVANCED_SOUNDS_SELECT_FORMATS = 0x15310000; - - // TvSettings > Display & Sound > Advanced sound settings > Select formats > - // Auto... - DISPLAY_SOUND_ADVANCED_SOUNDS_SELECT_FORMATS_AUTO = 0x15311000; - - // TvSettings > Display & Sound > Advanced sound settings > Select formats > - // None... - DISPLAY_SOUND_ADVANCED_SOUNDS_SELECT_FORMATS_NONE = 0x15312000; - - // TvSettings > Display & Sound > Advanced sound settings > Select formats > - // Manual... - DISPLAY_SOUND_ADVANCED_SOUNDS_SELECT_FORMATS_MANUAL = 0x15313000; - - // TvSettings > Display & Sound > Advanced sound settings > - // Dolby AC-4 (toggle) - DISPLAY_SOUND_ADVANCED_SOUNDS_DAC4 = 0x15320000; - - // TvSettings > Display & Sound > Advanced sound settings > - // Dolby Atmos in Dolby Digital Plus (toggle) - DISPLAY_SOUND_ADVANCED_SOUNDS_DADDP = 0x15330000; - - // TvSettings > Display & Sound > Advanced sound settings > - // Dolby Digital (toggle) - DISPLAY_SOUND_ADVANCED_SOUNDS_DD = 0x15340000; - - // TvSettings > Display & Sound > Advanced sound settings > - // Dolby Digital Plus (toggle) - DISPLAY_SOUND_ADVANCED_SOUNDS_DDP = 0x15350000; - - // TvSettings > Display & Sound > Advanced sound settings > DTS (toggle) - DISPLAY_SOUND_ADVANCED_SOUNDS_DTS = 0x15360000; - - // TvSettings > Display & Sound > Advanced sound settings > DTS-HD (toggle) - DISPLAY_SOUND_ADVANCED_SOUNDS_DTSHD = 0x15370000; - - // TvSettings > Display & Sound > Advanced sound settings > AAC (toggle) - DISPLAY_SOUND_ADVANCED_SOUNDS_AAC = 0x15380000; - - // TvSettings > Display & Sound > Advanced sound settings > - // Dolby TrueHD (toggle) - DISPLAY_SOUND_ADVANCED_SOUNDS_DTHD = 0x15390000; - - // TvSettings > Apps - APPS = 0x16000000; - - // TvSettings > Apps > See all apps - APPS_ALL_APPS = 0x16100000; - - // TvSettings > Apps > See all apps > [An app entry] - APPS_ALL_APPS_APP_ENTRY = 0x16110000; - - // TvSettings > Apps > See all apps > [An app entry] > Open - APPS_ALL_APPS_APP_ENTRY_OPEN = 0x16111000; - - // TvSettings > Apps > See all apps > [An app entry] > Force stop - APPS_ALL_APPS_APP_ENTRY_FORCE_STOP = 0x16112000; - - // TvSettings > Apps > See all apps > [An app entry] > Uninstall - APPS_ALL_APPS_APP_ENTRY_UNINSTALL = 0x16113000; - - // TvSettings > Apps > See all apps > [An app entry] > Uninstall updates - APPS_ALL_APPS_APP_ENTRY_UNINSTALL_UPDATES = 0x16114000; - - // TvSettings > Apps > See all apps > [An app entry] > Disable - APPS_ALL_APPS_APP_ENTRY_DISABLE = 0x16115000; - - // TvSettings > Apps > See all apps > [An app entry] > Clear data - APPS_ALL_APPS_APP_ENTRY_CLEAR_DATA = 0x16116000; - - // TvSettings > Apps > See all apps > [An app entry] > Clear cache - APPS_ALL_APPS_APP_ENTRY_CLEAR_CACHE = 0x16117000; - - // TvSettings > Apps > See all apps > [An app entry] > Clear defaults - APPS_ALL_APPS_APP_ENTRY_CLEAR_DEFAULTS = 0x16118000; - - // TvSettings > Apps > See all apps > [An app entry] > - // Notifications (toggle) - APPS_ALL_APPS_APP_ENTRY_NOTIFICATIONS = 0x16119000; - - // TvSettings > Apps > See all apps > [An app entry] > Permissions - APPS_ALL_APPS_APP_ENTRY_PERMISSIONS = 0x1611A000; - - // TvSettings > Apps > See all apps > [An app entry] > Enable - APPS_ALL_APPS_APP_ENTRY_ENABLE = 0x1611B000; - - // TvSettings > Apps > See all apps > [An app entry] > Open source licenses - APPS_ALL_APPS_APP_ENTRY_LICENSES = 0x1611C000; - - // TvSettings > Apps > See all apps > Show system apps - APPS_ALL_APPS_SHOW_SYSTEM_APPS = 0x16120000; - - // TvSettings > Apps > App permissions - APPS_APP_PERMISSIONS = 0x16200000; - - // TvSettings > Apps > App permission > Body sensors - APPS_APP_PERMISSIONS_BODY_SENSORS = 0x16210000; - - // TvSettings > Apps > App permission > Calendar - APPS_APP_PERMISSIONS_CALENDAR = 0x16220000; - - // TvSettings > Apps > App permission > Call logs - APPS_APP_PERMISSIONS_CALL_LOGS = 0x16230000; - - // TvSettings > Apps > App permission > Camera - APPS_APP_PERMISSIONS_CAMERA = 0x16240000; - - // TvSettings > Apps > App permission > Contacts - APPS_APP_PERMISSIONS_CONTACTS = 0x16250000; - - // TvSettings > Apps > App permission > Location - APPS_APP_PERMISSIONS_LOCATION = 0x16260000; - - // TvSettings > Apps > App permission > Microphone - APPS_APP_PERMISSIONS_MICROPHONE = 0x16270000; - - // TvSettings > Apps > App permission > Phone - APPS_APP_PERMISSIONS_PHONE = 0x16280000; - - // TvSettings > Apps > App permission > Physical activity - APPS_APP_PERMISSIONS_PHYSICAL_ACTIVITY = 0x16290000; - - // TvSettings > Apps > App permission > SMS - APPS_APP_PERMISSIONS_SMS = 0x162A0000; - - // TvSettings > Apps > App permission > Storage - APPS_APP_PERMISSIONS_STORAGE = 0x162B0000; - - // TvSettings > Apps > App permission > Additional permissions - APPS_APP_PERMISSIONS_ADDITIONAL = 0x162C0000; - - // TvSettings > Apps > App permission > Additional permissions > - // real all TV listings - APPS_APP_PERMISSIONS_ADDITIONAL_READ_TV_LISTINGS = 0x162C1000; - - // TvSettings > Apps > App permission > Additional permissions > - // real instant messages - APPS_APP_PERMISSIONS_ADDITIONAL_READ_INSTANT_MESSAGES = 0x162C2000; - - // TvSettings > Apps > App permission > Additional permissions > - // write instant messages - APPS_APP_PERMISSIONS_ADDITIONAL_WRITE_INSTANT_MESSAGES = 0x162C3000; - - // TvSettings > Apps > Special app access - APPS_SPECIAL_APP_ACCESS = 0x16300000; - - // TvSettings > Apps > Special app access > Energy optimization - APPS_SPECIAL_APP_ACCESS_ENERGY_OPTIMIZATION = 0x16310000; - - // TvSettings > Apps > Special app access > Usage access - APPS_SPECIAL_APP_ACCESS_USAGE_ACCESS = 0x16320000; - - // TvSettings > Apps > Special app access > Notification access - APPS_SPECIAL_APP_ACCESS_NOTIFICATION_ACCESS = 0x16330000; - - // TvSettings > Apps > Special app access > Display over other apps - APPS_SPECIAL_APP_ACCESS_DISPLAY_OVER_OTHERS = 0x16340000; - - // TvSettings > Apps > Special app access > Modify system settings - APPS_SPECIAL_APP_ACCESS_MODIFY_SYSTEM_SETTINGS = 0x16350000; - - // TvSettings > Apps > Special app access > Picture-in-picture - APPS_SPECIAL_APP_ACCESS_PICTURE_IN_PICTURE = 0x16360000; - - // TvSettings > Apps > Security & restrictions - APPS_SECURITY_RESTRICTIONS = 0x16400000; - - // TvSettings > Apps > Security & restrictions > Unknown sources - APPS_SECURITY_RESTRICTIONS_UNKNOWN_SOURCES = 0x16410000; - - // TvSettings > Apps > Security & restrictions > Verify apps (toggle) - APPS_SECURITY_RESTRICTIONS_VERIFY_APPS = 0x16420000; - - // TvSettings > Apps > Security & restrictions > Create restricted profile - APPS_SECURITY_RESTRICTIONS_CREATE_PROFILE = 0x16430000; - - // TvSettings > Apps > Security & restrictions > Enter restricted profile - APPS_SECURITY_RESTRICTIONS_ENTER_PROFILE = 0x16440000; - - // TvSettings > Apps > Security & restrictions > - // Allowed apps (Restricted Profile) - APPS_SECURITY_RESTRICTIONS_PROFILE_ALLOWED_APPS = 0x16450000; - - // TvSettings > Apps > Security & restrictions > - // Change pin (Restricted Profile) - APPS_SECURITY_RESTRICTIONS_PROFILE_CHANGE_PIN = 0x16460000; - - // TvSettings > Apps > Security & restrictions > - // Delete restricted profile - APPS_SECURITY_RESTRICTIONS_DELETE_PROFILE = 0x16470000; - - // TvSettings > Apps > Security & restrictions > - // Exit restricted profile - APPS_SECURITY_RESTRICTIONS_EXIT_PROFILE = 0x16480000; - - // TvSettings > System (same as TvSettings > Device Preferences) - SYSTEM = 0x17000000; - - // TvSettings > System > About - SYSTEM_ABOUT = 0x17100000; - - // TvSettings > System > System update - SYSTEM_ABOUT_SYSTEM_UPDATE = 0x17110000; - - // TvSettings > System > Device name - SYSTEM_ABOUT_DEVICE_NAME = 0x17120000; - - // TvSettings > System > Factory reset - SYSTEM_ABOUT_FACTORY_RESET = 0x17130000; - - // TvSettings > System > Status - SYSTEM_ABOUT_STATUS = 0x17140000; - - // TvSettings > System > Legal information - SYSTEM_ABOUT_LEGAL_INFO = 0x17150000; - - // TvSettings > System > Legal information > Open source licenses - SYSTEM_ABOUT_LEGAL_INFO_OPEN_SOURCE = 0x17151000; - - // TvSettings > System > Legal information > Google legal - SYSTEM_ABOUT_LEGAL_INFO_GOOGLE_LEGAL = 0x17152000; - - // TvSettings > System > Legal information > System WebView licenses - SYSTEM_ABOUT_LEGAL_INFO_SYSTEM_WEBVIEW = 0x17153000; - - // TvSettings > System > Build - SYSTEM_ABOUT_BUILD = 0x17160000; - - // TvSettings > System > Date & time - SYSTEM_DATE_TIME = 0x17200000; - - // TvSettings > System > Date & time > Automatic data & time - SYSTEM_DATE_TIME_AUTOMATIC = 0x17210000; - - // TvSettings > System > Date & time > Automatic data & time > - // Use network-provided time - SYSTEM_DATE_TIME_AUTOMATIC_USE_NETWORK_TIME = 0x17211000; - - // TvSettings > System > Date & time > Automatic data & time > Off - SYSTEM_DATE_TIME_AUTOMATIC_OFF = 0x17212000; - - // TvSettings > System > Date & time > Set date - SYSTEM_DATE_TIME_SET_DATE = 0x17220000; - - // TvSettings > System > Date & time > Set time - SYSTEM_DATE_TIME_SET_TIME = 0x17230000; - - // TvSettings > System > Date & time > Set time zone - SYSTEM_DATE_TIME_SET_TIME_ZONE = 0x17240000; - - // TvSettings > System > Date & time > Set time zone > [A time zone button] - SYSTEM_DATE_TIME_SET_TIME_ZONE_BUTTON = 0x17241000; - - // TvSettings > System > Date & time > Use 24-hour format (toggle) - SYSTEM_DATE_TIME_USE_24_HOUR_FORMAT = 0x17250000; - - // TvSettings > System > Language - SYSTEM_LANGUAGE = 0x17300000; - - // TvSettings > System > Language > [A language button] - SYSTEM_LANGUAGE_BUTTON = 0x17310000; - - // TvSettings > System > Keyboard - SYSTEM_KEYBOARD = 0x17400000; - - // TvSettings > System > Keyboard > Current keyboard - SYSTEM_KEYBOARD_CURRENT_KEYBOARD = 0x17410000; - - // TvSettings > System > Keyboard > Gboard Settings - SYSTEM_KEYBOARD_GBOARD_SETTINGS = 0x17420000; - - // TvSettings > System > Keyboard > Gboard Settings > Languages - SYSTEM_KEYBOARD_GBOARD_SETTINGS_LANGUAGES = 0x17421000; - - // TvSettings > System > Keyboard > Gboard Settings > Terms of services - SYSTEM_KEYBOARD_GBOARD_SETTINGS_TOS = 0x17422000; - - // TvSettings > System > Keyboard > Gboard Settings > Privacy policy - SYSTEM_KEYBOARD_GBOARD_SETTINGS_PRIVACY_POLICY = 0x17423000; - - // TvSettings > System > Keyboard > Gboard Settings > Open source licenses - SYSTEM_KEYBOARD_GBOARD_SETTINGS_OPEN_SOURCE = 0x17424000; - - // TvSettings > System > Keyboard > Gboard Settings > - // Share usage statistics (toggle) - SYSTEM_KEYBOARD_GBOARD_SETTINGS_SHARE_USAGE_STATS = 0x17425000; - - // TvSettings > System > Keyboard > Manage keyboards - SYSTEM_KEYBOARD_MANAGE_KEYBOARDS = 0x17430000; - - // TvSettings > System > Storage - SYSTEM_STORAGE = 0x17500000; - - // TvSettings > System > Internal shared storage - SYSTEM_STORAGE_INTERNAL_STORAGE = 0x17510000; - - // TvSettings > System > Internal shared storage > Apps - SYSTEM_STORAGE_INTERNAL_STORAGE_APPS = 0x17511000; - - // TvSettings > System > Internal shared storage > - // Cached data (brings up "Clear cached data?" dialog upon click) - SYSTEM_STORAGE_INTERNAL_STORAGE_CACHED = 0x17512000; - - // TvSettings > System > Ambient mode - SYSTEM_AMBIENT = 0x17600000; - - // TvSettings > System > Ambient mode > Start now - SYSTEM_AMBIENT_START = 0x17610000; - - // TvSettings > System > Ambient mode > Settings - SYSTEM_AMBIENT_SETTINGS = 0x17620000; - - // TvSettings > System > Ambient mode > Settings > Google Photos (Channels) - SYSTEM_AMBIENT_SETTINGS_CHANNEL_GP = 0x17621000; - - // TvSettings > System > Ambient mode > Settings > Art gallery (Channels) - SYSTEM_AMBIENT_SETTINGS_CHANNEL_AG = 0x17622000; - - // TvSettings > System > Ambient mode > Settings > - // Cinematic videos (Channels) - SYSTEM_AMBIENT_SETTINGS_CHANNEL_CV = 0x17623000; - - // TvSettings > System > Ambient mode > Settings > Experimental (Channels) - SYSTEM_AMBIENT_SETTINGS_CHANNEL_EXP = 0x17624000; - - // TvSettings > System > Ambient mode > Settings > Weather - SYSTEM_AMBIENT_SETTINGS_WEATHER = 0x17625000; - - // TvSettings > System > Ambient mode > Settings > Weather > Hide - SYSTEM_AMBIENT_SETTINGS_WEATHER_HIDE = 0x17625100; - - // TvSettings > System > Ambient mode > Settings > Weather > Celsius (Unit) - SYSTEM_AMBIENT_SETTINGS_WEATHER_UNIT_C = 0x17625200; - - // TvSettings > System > Ambient mode > Settings > Weather > - // Fahrenheit (Unit) - SYSTEM_AMBIENT_SETTINGS_WEATHER_UNIT_F = 0x17625300; - - // TvSettings > System > Ambient mode > Settings > Weather > Both (Unit) - SYSTEM_AMBIENT_SETTINGS_WEATHER_UNIT_BOTH = 0x17625400; - - // TvSettings > System > Ambient mode > Settings > Time - SYSTEM_AMBIENT_SETTINGS_TIME = 0x17626000; - - // TvSettings > System > Ambient mode > Settings > Time > Hide - SYSTEM_AMBIENT_SETTINGS_TIME_HIDE = 0x17626100; - - // TvSettings > System > Ambient mode > Settings > Time > Show - SYSTEM_AMBIENT_SETTINGS_TIME_SHOW = 0x17626200; - - // TvSettings > System > Ambient mode > Settings > Device information - SYSTEM_AMBIENT_SETTINGS_DEVICE_INFO = 0x17627000; - - // TvSettings > System > Ambient mode > Settings > Device information > Hide - SYSTEM_AMBIENT_SETTINGS_DEVICE_INFO_HIDE = 0x17627100; - - // TvSettings > System > Ambient mode > Settings > Device information > Show - SYSTEM_AMBIENT_SETTINGS_DEVICE_INFO_SHOW = 0x17627200; - - // TvSettings > System > Ambient mode > Settings > Personal photo data - SYSTEM_AMBIENT_SETTINGS_PPD = 0x17628000; - - // TvSettings > System > Ambient mode > Settings > Personal photo data > - // Hide - SYSTEM_AMBIENT_SETTINGS_PPD_HIDE = 0x17628100; - - // TvSettings > System > Ambient mode > Settings > Personal photo data > - // Show - SYSTEM_AMBIENT_SETTINGS_PPD_SHOW = 0x17628200; - - // TvSettings > System > Ambient mode > Settings > Portrait Google Photos - SYSTEM_AMBIENT_SETTINGS_PGP = 0x17629000; - - // TvSettings > System > Ambient mode > Settings > Portrait Google Photos > - // Hide - SYSTEM_AMBIENT_SETTINGS_PGP_HIDE = 0x17629100; - - // TvSettings > System > Ambient mode > Settings > Portrait Google Photos > - // Show - SYSTEM_AMBIENT_SETTINGS_PGP_SHOW = 0x17629200; - - // TvSettings > System > Ambient mode > Settings > Portrait Google Photos > - // Show pairs - SYSTEM_AMBIENT_SETTINGS_PGP_SHOW_PAIRS = 0x17629300; - - // TvSettings > System > Ambient mode > Settings > Personal photo curation - SYSTEM_AMBIENT_SETTINGS_PPC = 0x1762A000; - - // TvSettings > System > Ambient mode > Settings > Personal photo curation > - // All albums - SYSTEM_AMBIENT_SETTINGS_PPC_ALL_ALBUMS = 0x1762A100; - - // TvSettings > System > Ambient mode > Settings > Personal photo curation > - // Live albums only - SYSTEM_AMBIENT_SETTINGS_PPC_LIVE_ALBUMS = 0x1762A200; - - // TvSettings > System > Ambient mode > Settings > Slideshow speed - SYSTEM_AMBIENT_SETTINGS_SLIDE_SPEED = 0x1762B000; - - // TvSettings > System > Ambient mode > Settings > Slideshow speed > 5s - SYSTEM_AMBIENT_SETTINGS_SLIDE_SPEED_5S = 0x1762B100; - - // TvSettings > System > Ambient mode > Settings > Slideshow speed > 10s - SYSTEM_AMBIENT_SETTINGS_SLIDE_SPEED_10S = 0x1762B200; - - // TvSettings > System > Ambient mode > Settings > Slideshow speed > 30s - SYSTEM_AMBIENT_SETTINGS_SLIDE_SPEED_30S = 0x1762B300; - - // TvSettings > System > Ambient mode > Settings > Slideshow speed > 1m - SYSTEM_AMBIENT_SETTINGS_SLIDE_SPEED_1M = 0x1762B400; - - // TvSettings > System > Ambient mode > Settings > Slideshow speed > 3m - SYSTEM_AMBIENT_SETTINGS_SLIDE_SPEED_3M = 0x1762B500; - - // TvSettings > System > Ambient mode > Settings > Slideshow speed > 5m - SYSTEM_AMBIENT_SETTINGS_SLIDE_SPEED_5M = 0x1762B600; - - // TvSettings > System > Ambient mode > Settings > Slideshow speed > 10m - SYSTEM_AMBIENT_SETTINGS_SLIDE_SPEED_10M = 0x1762B700; - - // TvSettings > System > Energy saver - SYSTEM_ENERGYSAVER = 0x17700000; - - // TvSettings > System > Energy saver > Turn off display after - SYSTEM_ENERGYSAVER_START_DELAY = 0x17710000; - - // TvSettings > System > Energy saver > Turn off display after > 15 minutes - SYSTEM_ENERGYSAVER_START_DELAY_15M = 0x17711000; - - // TvSettings > System > Energy saver > Turn off display after > 30 minutes - SYSTEM_ENERGYSAVER_START_DELAY_30M = 0x17712000; - - // TvSettings > System > Energy saver > Turn off display after > 1 hour - SYSTEM_ENERGYSAVER_START_DELAY_1H = 0x17713000; - - // TvSettings > System > Energy saver > Turn off display after > 3 hours - SYSTEM_ENERGYSAVER_START_DELAY_3H = 0x17714000; - - // TvSettings > System > Energy saver > Turn off display after > 6 hours - SYSTEM_ENERGYSAVER_START_DELAY_6H = 0x17715000; - - // TvSettings > System > Energy saver > Turn off display after > 12 hours - SYSTEM_ENERGYSAVER_START_DELAY_12H = 0x17716000; - - // TvSettings > System > Energy saver > Turn off display after > Never - SYSTEM_ENERGYSAVER_START_DELAY_NEVER = 0x17717000; - - // TvSettings > System > Accessibility - SYSTEM_A11Y = 0x17800000; - - // TvSettings > System > Accessibility > Captions - SYSTEM_A11Y_CAPTIONS = 0x17810000; - - // TvSettings > System > Accessibility > Captions > Display (toggle) - SYSTEM_A11Y_CAPTIONS_DISPLAY_ON_OFF = 0x17811000; - - // TvSettings > System > Accessibility > Captions > Language - SYSTEM_A11Y_CAPTIONS_LANGUAGE = 0x17812000; - - // TvSettings > System > Accessibility > Captions > Language > [A language] - SYSTEM_A11Y_CAPTIONS_LANGUAGE_BUTTON = 0x17812100; - - // TvSettings > System > Accessibility > Captions > Text size - SYSTEM_A11Y_CAPTIONS_TEXT_SIZE = 0x17813000; - - // TvSettings > System > Accessibility > Captions > Text size > Very small - SYSTEM_A11Y_CAPTIONS_TEXT_SIZE_VERY_SMALL = 0x17813100; - - // TvSettings > System > Accessibility > Captions > Text size > Small - SYSTEM_A11Y_CAPTIONS_TEXT_SIZE_SMALL = 0x17813200; - - // TvSettings > System > Accessibility > Captions > Text size > Normal - SYSTEM_A11Y_CAPTIONS_TEXT_SIZE_NORMAL = 0x17813300; - - // TvSettings > System > Accessibility > Captions > Text size > Large - SYSTEM_A11Y_CAPTIONS_TEXT_SIZE_LARGE = 0x17813400; - - // TvSettings > System > Accessibility > Captions > Text size > Very large - SYSTEM_A11Y_CAPTIONS_TEXT_SIZE_VERY_LARGE = 0x17813500; - - // TvSettings > System > Accessibility > Captions > - // White on black (radio button) - SYSTEM_A11Y_CAPTIONS_WHITE_ON_BLACK = 0x17814000; - - // TvSettings > System > Accessibility > Captions > - // Black on white (radio button) - SYSTEM_A11Y_CAPTIONS_BLACK_ON_WHITE = 0x17815000; - - // TvSettings > System > Accessibility > Captions > - // Yellow on black (radio button) - SYSTEM_A11Y_CAPTIONS_YELLOW_ON_BLACK = 0x17816000; - - // TvSettings > System > Accessibility > Captions > - // Yellow on blue (radio button) - SYSTEM_A11Y_CAPTIONS_YELLOW_ON_BLUE = 0x17817000; - - // TvSettings > System > Accessibility > Captions > Custom - SYSTEM_A11Y_CAPTIONS_CUSTOM = 0x17818000; - - // TvSettings > System > Accessibility > Captions > Custom > Font family - SYSTEM_A11Y_CAPTIONS_CUSTOM_FONT = 0x17818100; - - // TvSettings > System > Accessibility > Captions > Custom > Text color - SYSTEM_A11Y_CAPTIONS_CUSTOM_TEXT_COLOR = 0x17818200; - - // TvSettings > System > Accessibility > Captions > Custom > Text opacity - SYSTEM_A11Y_CAPTIONS_CUSTOM_TEXT_OPACITY = 0x17818300; - - // TvSettings > System > Accessibility > Captions > Custom > Edge type - SYSTEM_A11Y_CAPTIONS_CUSTOM_EDGE_TYPE = 0x17818400; - - // TvSettings > System > Accessibility > Captions > Custom > Edge color - SYSTEM_A11Y_CAPTIONS_CUSTOM_EDGE_COLOR = 0x17818500; - - // TvSettings > System > Accessibility > Captions > Custom > - // Show background (toggle) - SYSTEM_A11Y_CAPTIONS_SHOW_BACKGROUND = 0x17818600; - - // TvSettings > System > Accessibility > Captions > Custom > - // Background color - SYSTEM_A11Y_CAPTIONS_BACKGROUND_COLOR = 0x17818700; - - // TvSettings > System > Accessibility > Captions > Custom > - // Background opacity - SYSTEM_A11Y_CAPTIONS_BACKGROUND_OPACITY = 0x17818800; - - // TvSettings > System > Accessibility > Captions > Custom > - // Show window (toggle) - SYSTEM_A11Y_CAPTIONS_SHOW_WINDOW = 0x17818900; - - // TvSettings > System > Accessibility > Captions > Custom > Window color - SYSTEM_A11Y_CAPTIONS_WINDOW_COLOR = 0x17818A00; - - // TvSettings > System > Accessibility > Captions > Custom > Window opacity - SYSTEM_A11Y_CAPTIONS_WINDOW_OPACITY = 0x17818B00; - - // TvSettings > System > Accessibility > High contrast text (toggle) - SYSTEM_A11Y_HIGH_CONTRAST_TEXT = 0x17820000; - - // TvSettings > System > Accessibility > Text to speech - SYSTEM_A11Y_TTS = 0x17830000; - - // TvSettings > System > Accessibility > Text to speech > [Select an engine] - SYSTEM_A11Y_TTS_ENGINE_SELECT = 0x17831000; - - // TvSettings > System > Accessibility > Text to speech > - // Engine configuration - SYSTEM_A11Y_TTS_ENGINE_CONFIG = 0x17832000; - - // TvSettings > System > Accessibility > Text to speech > - // Engine configuration > Language - SYSTEM_A11Y_TTS_ENGINE_CONFIG_LANGUAGE = 0x17832100; - - // TvSettings > System > Accessibility > Text to speech > - // Engine configuration > Language > Button - SYSTEM_A11Y_TTS_ENGINE_CONFIG_LANGUAGE_CHOOSE_LANGUAGE = 0x17832110; - - // TvSettings > System > Accessibility > Text to speech > - // Engine configuration > Settings for Google Text-to-speech Engine - SYSTEM_A11Y_TTS_ENGINE_CONFIG_SETTINGS_GTTS_ENGINE = 0x17832200; - - // TvSettings > System > Accessibility > Text to speech > - // Engine configuration > Install voice data - SYSTEM_A11Y_TTS_ENGINE_CONFIG_INSTALL_VOICE_DATA = 0x17832300; - - // TvSettings > System > Accessibility > Text to speech > Speech rate - SYSTEM_A11Y_TTS_SPEECH_RATE = 0x17833000; - - // TvSettings > System > Accessibility > Text to speech > - // Listen to an example - SYSTEM_A11Y_TTS_LISTEN_EXAMPLE = 0x17834000; - - // TvSettings > System > Accessibility > Accessibility shortcut - SYSTEM_A11Y_SHORTCUT = 0x17840000; - - // TvSettings > System > Accessibility > Accessibility shortcut > - // Enable (toggle) - SYSTEM_A11Y_SHORTCUT_ON_OFF = 0x17841000; - - // TvSettings > System > Accessibility > Accessibility shortcut > - // Shortcut services - SYSTEM_A11Y_SHORTCUT_SERVICE = 0x17842000; - - // TvSettings > System > Accessibility > TalkBack - SYSTEM_A11Y_TALKBACK = 0x17850000; - - // TvSettings > System > Accessibility > TalkBack > Enable (toggle) - SYSTEM_A11Y_TALKBACK_ON_OFF = 0x17851000; - - // TvSettings > System > Accessibility > TalkBack > Configuration - SYSTEM_A11Y_TALKBACK_CONFIG = 0x17852000; - - // TvSettings > System > Accessibility > Accessibility Menu - SYSTEM_A11Y_A11Y_MENU = 0x17860000; - - // TvSettings > System > Accessibility > Accessibility Menu > - // Enable (toggle) - SYSTEM_A11Y_A11Y_MENU_ON_OFF = 0x17861000; - - // TvSettings > System > Accessibility > Accessibility Menu > Configuration - SYSTEM_A11Y_A11Y_MENU_CONFIG = 0x17862000; - - // TvSettings > System > Accessibility > Select to Speak - SYSTEM_A11Y_STS = 0x17870000; - - // TvSettings > System > Accessibility > Select to Speak > Enable (toggle) - SYSTEM_A11Y_STS_ON_OFF = 0x17871000; - - // TvSettings > System > Accessibility > Select to Speak > Configuration - SYSTEM_A11Y_STS_CONFIG = 0x17872000; - - // TvSettings > System > Accessibility > Switch Access - SYSTEM_A11Y_SWITCH_ACCESS = 0x17880000; - - // TvSettings > System > Accessibility > Switch Access > Enable (Toggle) - SYSTEM_A11Y_SWITCH_ACCESS_ON_OFF = 0x17881000; - - // TvSettings > System > Accessibility > Switch Access > Configuration - SYSTEM_A11Y_SWITCH_ACCESS_CONFIG = 0x17882000; - - // TvSettings > System > Reboot - SYSTEM_REBOOT = 0x17900000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) - PREFERENCES_HOME_SCREEN = 0x17A00000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Customize channels - PREFERENCES_HOME_SCREEN_CUSTOMIZE_CHANNELS = 0x17A10000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Customize channels > Play Next - PREFERENCES_HOME_SCREEN_CUSTOMIZE_CHANNELS_PN = 0x17A11000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Customize channels > Play Next > On (toggle) - PREFERENCES_HOME_SCREEN_CUSTOMIZE_CHANNELS_PN_ON_OFF = 0x17A11100; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Customize channels > Play Next > Google Play Movies & TV (toggle) - PREFERENCES_HOME_SCREEN_CUSTOMIZE_CHANNELS_PN_GPMT = 0x17A11200; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Customize channels > Play Next > Google Play Music (toggle) - PREFERENCES_HOME_SCREEN_CUSTOMIZE_CHANNELS_PN_GPM = 0x17A11300; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Customize channels > Play Next > Promotional channels (toggle) - PREFERENCES_HOME_SCREEN_CUSTOMIZE_CHANNELS_PN_PROMOTIONAL = 0x17A11400; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Customize channels > Home screen channels - PREFERENCES_HOME_SCREEN_CUSTOMIZE_CHANNELS_HOME_SCREEN = 0x17A12000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Customize channels > Promotional channels - PREFERENCES_HOME_SCREEN_CUSTOMIZE_CHANNELS_PROMOTIONAL = 0x17A13000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Enable video previews (toggle) - PREFERENCES_HOME_SCREEN_VIDEO_PREVIEWS = 0x17A20000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Enable audio previews (toggle) - PREFERENCES_HOME_SCREEN_AUDIO_PREVIEWS = 0x17A30000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Reorder apps - PREFERENCES_HOME_SCREEN_REORDER_APPS = 0x17A40000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Reorder games - PREFERENCES_HOME_SCREEN_REORDER_GAMES = 0x17A50000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Android TV Home open source licenses - PREFERENCES_HOME_SCREEN_ATVH_OPEN_SOURCE = 0x17A60000; - - // TvSettings > Device Preferences > Home screen (in classic TvSettings) > - // Android TV Core Services open source licenses - PREFERENCES_HOME_SCREEN_ATVCS_OPEN_SOURCE = 0x17A70000; - - // TvSettings > Device Preferences > Google Assistant - PREFERENCES_ASSISTANT = 0x17B00000; - - // TvSettings > Device Preferences > Google Assistant > Accounts - PREFERENCES_ASSISTANT_ACCOUNTS = 0x17B10000; - - // TvSettings > Device Preferences > Google Assistant > Accept permissions - PREFERENCES_ASSISTANT_ACCEPT_PERMISSIONS = 0x17B20000; - - // TvSettings > Device Preferences > Google Assistant > View permissions - PREFERENCES_ASSISTANT_VIEW_PERMISSIONS = 0x17B30000; - - // TvSettings > Device Preferences > Google Assistant > Searchable apps - // (aliasing ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_SEARCHABLE_APPS) - PREFERENCES_ASSISTANT_SEARCHABLE_APPS = 0x12133000; - - // TvSettings > Device Preferences > Google Assistant > SafeSearch filter - // (aliasing ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_SAFE_SEARCH) - PREFERENCES_ASSISTANT_SAFESEARCH_FILTER = 0x12131000; - - // TvSettings > Device Preferences > Google Assistant > - // Block offensive words - // (aliasing ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_BLOCK_OFFENSIVE) - PREFERENCES_ASSISTANT_BLOCK_OFFENSIVE = 0x12132000; - - // TvSettings > Device Preferences > Google Assistant > Open source licenses - PREFERENCES_ASSISTANT_OPEN_SOURCE = 0x17B40000; - - // TvSettings > Device Preferences > Chromecast Android Shell - PREFERENCES_CHROMECAST_SHELL = 0x17C00000; - - // TvSettings > Device Preferences > Chromecast Android Shell > - // Open source licenses - PREFERENCES_CHROMECAST_SHELL_OPEN_SOURCE = 0x17C10000; - - // TvSettings > Device Preferences > Screen saver - PREFERENCES_SCREENSAVER = 0x17D00000; - - // TvSettings > Device Preferences > Screen saver > Screen saver (chooser) - PREFERENCES_SCREENSAVER_CHOOSER = 0x17D10000; - - // TvSettings > Device Preferences > Screen saver > Screen saver (chooser) > - // Turn screen off - PREFERENCES_SCREENSAVER_CHOOSER_SCREEN_OFF = 0x17D11000; - - // TvSettings > Device Preferences > Screen saver > Screen saver (chooser) > - // Backdrop - PREFERENCES_SCREENSAVER_CHOOSER_BACKDROP = 0x17D12000; - - // TvSettings > Device Preferences > Screen saver > Screen saver (chooser) > - // Colors - PREFERENCES_SCREENSAVER_CHOOSER_COLORS = 0x17D13000; - - // TvSettings > Device Preferences > Screen saver > When to start - PREFERENCES_SCREENSAVER_START_DELAY = 0x17D20000; - - // TvSettings > Device Preferences > Screen saver > When to start > - // 5 minutes - PREFERENCES_SCREENSAVER_START_DELAY_5M = 0x17D21000; - - // TvSettings > Device Preferences > Screen saver > When to start > - // 15 minutes - PREFERENCES_SCREENSAVER_START_DELAY_15M = 0x17D22000; - - // TvSettings > Device Preferences > Screen saver > When to start > - // 30 minutes - PREFERENCES_SCREENSAVER_START_DELAY_30M = 0x17D23000; - - // TvSettings > Device Preferences > Screen saver > When to start > - // 1 hour - PREFERENCES_SCREENSAVER_START_DELAY_1H = 0x17D24000; - - // TvSettings > Device Preferences > Screen saver > When to start > - // 2 hours - PREFERENCES_SCREENSAVER_START_DELAY_2H = 0x17D25000; - - // TvSettings > Device Preferences > Screen saver > Start now - PREFERENCES_SCREENSAVER_START_NOW = 0x17D30000; - - // TvSettings > Connected Devices (Slice) - CONNECTED_SLICE = 0x18000000; - - // TvSettings > Connected Devices (Slice) > Connect remote or headphones - CONNECTED_SLICE_CONNECT_NEW_DEVICES = 0x18100000; - - // TvSettings > Connected Devices (Slice) > [A connected device] - CONNECTED_SLICE_DEVICE_ENTRY = 0x18200000; - - // TvSettings > Connected Devices (Slice) > [A connected device] > - // Remote update - CONNECTED_SLICE_DEVICE_ENTRY_UPDATE = 0x18210000; - - // TvSettings > Connected Devices (Slice) > [A connected device] > Rename - CONNECTED_SLICE_DEVICE_ENTRY_RENAME = 0x18220000; - - // TvSettings > Connected Devices (Slice) > [A connected device] > Forget - CONNECTED_SLICE_DEVICE_ENTRY_FORGET = 0x18230000; - - // TvSettings > Connected Devices (Slice) > HDMI-CEC - CONNECTED_SLICE_HDMICEC = 0x18300000; - - // TvSettings > Connected Devices (Slice) > HDMI-CEC > Enable (toggle) - CONNECTED_SLICE_HDMICEC_ON_OFF = 0x18310000; - - // TvSettings > Connected Devices (aliasing CONNECTED_SLICE) - CONNECTED_CLASSIC = 0x18000000; - - // TvSettings > Connected Devices > Connect remote - // (aliasing CONNECTED_SLICE_CONNECT_NEW_DEVICES) - CONNECTED_CLASSIC_CONNECT_REMOTE = 0x18100000; - - // TvSettings > Connected Devices > [A connected device] - // (aliasing CONNECTED_SLICE_DEVICE_ENTRY) - CONNECTED_CLASSIC_DEVICE_ENTRY = 0x18200000; - - // TvSettings > Connected Devices > [A connected device] > Update - // (aliasing CONNECTED_SLICE_DEVICE_ENTRY_UPDATE) - CONNECTED_CLASSIC_DEVICE_ENTRY_UPDATE = 0x18210000; - - // TvSettings > Connected Devices > [A connected device] > Rename - // (aliasing CONNECTED_SLICE_DEVICE_ENTRY_RENAME) - CONNECTED_CLASSIC_DEVICE_ENTRY_RENAME = 0x18220000; - - // TvSettings > Connected Devices > [A connected device] > Forget - // (aliasing CONNECTED_SLICE_DEVICE_ENTRY_FORGET) - CONNECTED_CLASSIC_DEVICE_ENTRY_FORGET = 0x18230000; - - // TvSettings > Connected Devices > HDMI-CEC - // (aliasing CONNECTED_SLICE_HDMICEC) - CONNECTED_CLASSIC_HDMICEC = 0x18300000; - - // TvSettings > Connected Devices > HDMI-CEC > Enable (toggle) - // (aliasing CONNECTED_SLICE_HDMICEC_ON_OFF) - CONNECTED_CLASSIC_HDMICEC_ON_OFF = 0x18310000; - - // TvSettings > Help & Feedback - FEEDBACK = 0x19000000; - - // TvSettings > Help & Feedback > Send feedback - FEEDBACK_SEND = 0x19100000; -} diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto deleted file mode 100644 index dc60ededf965..000000000000 --- a/core/proto/android/bluetooth/enums.proto +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.bluetooth; - -option java_outer_classname = "BluetoothProtoEnums"; -option java_multiple_files = true; - -// Bluetooth connection states. -enum ConnectionStateEnum { - CONNECTION_STATE_DISCONNECTED = 0; - CONNECTION_STATE_CONNECTING = 1; - CONNECTION_STATE_CONNECTED = 2; - CONNECTION_STATE_DISCONNECTING = 3; -} - -// Bluetooth Adapter Enable and Disable Reasons -enum EnableDisableReasonEnum { - ENABLE_DISABLE_REASON_UNSPECIFIED = 0; - ENABLE_DISABLE_REASON_APPLICATION_REQUEST = 1; - ENABLE_DISABLE_REASON_AIRPLANE_MODE = 2; - ENABLE_DISABLE_REASON_DISALLOWED = 3; - ENABLE_DISABLE_REASON_RESTARTED = 4; - ENABLE_DISABLE_REASON_START_ERROR = 5; - ENABLE_DISABLE_REASON_SYSTEM_BOOT = 6; - ENABLE_DISABLE_REASON_CRASH = 7; - ENABLE_DISABLE_REASON_USER_SWITCH = 8; - ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9; - ENABLE_DISABLE_REASON_FACTORY_RESET = 10; - ENABLE_DISABLE_REASON_INIT_FLAGS_CHANGED = 11; -} - -enum DirectionEnum { - DIRECTION_UNKNOWN = 0; - DIRECTION_OUTGOING = 1; - DIRECTION_INCOMING = 2; -} - -// First item is the default value, other values follow Bluetooth spec definition -enum LinkTypeEnum { - // Link type is at most 1 byte (0xFF), thus 0xFFF must not be a valid value - LINK_TYPE_UNKNOWN = 0xFFF; - LINK_TYPE_SCO = 0x00; - LINK_TYPE_ACL = 0x01; - LINK_TYPE_ESCO = 0x02; -} - -enum DeviceInfoSrcEnum { - DEVICE_INFO_SRC_UNKNOWN = 0; - // Within Android Bluetooth stack - DEVICE_INFO_INTERNAL = 1; - // Outside Android Bluetooth stack - DEVICE_INFO_EXTERNAL = 2; -} - -enum DeviceTypeEnum { - DEVICE_TYPE_UNKNOWN = 0; - DEVICE_TYPE_CLASSIC = 1; - DEVICE_TYPE_LE = 2; - DEVICE_TYPE_DUAL = 3; -} - -// Defined in frameworks/base/core/java/android/bluetooth/BluetoothDevice.java -enum TransportTypeEnum { - TRANSPORT_TYPE_AUTO = 0; - TRANSPORT_TYPE_BREDR = 1; - TRANSPORT_TYPE_LE = 2; -} - -// Bond state enum -// Defined in frameworks/base/core/java/android/bluetooth/BluetoothDevice.java -enum BondStateEnum { - BOND_STATE_UNKNOWN = 0; - BOND_STATE_NONE = 10; - BOND_STATE_BONDING = 11; - BOND_STATE_BONDED = 12; -} - -// Sub states within the bonding general state -enum BondSubStateEnum { - BOND_SUB_STATE_UNKNOWN = 0; - BOND_SUB_STATE_LOCAL_OOB_DATA_PROVIDED = 1; - BOND_SUB_STATE_LOCAL_PIN_REQUESTED = 2; - BOND_SUB_STATE_LOCAL_PIN_REPLIED = 3; - BOND_SUB_STATE_LOCAL_SSP_REQUESTED = 4; - BOND_SUB_STATE_LOCAL_SSP_REPLIED = 5; -} - -enum UnbondReasonEnum { - UNBOND_REASON_UNKNOWN = 0; - UNBOND_REASON_AUTH_FAILED = 1; - UNBOND_REASON_AUTH_REJECTED = 2; - UNBOND_REASON_AUTH_CANCELED = 3; - UNBOND_REASON_REMOTE_DEVICE_DOWN = 4; - UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5; - UNBOND_REASON_AUTH_TIMEOUT = 6; - UNBOND_REASON_REPEATED_ATTEMPTS = 7; - UNBOND_REASON_REMOTE_AUTH_CANCELED = 8; - UNBOND_REASON_REMOVED = 9; -} - -enum SocketTypeEnum { - SOCKET_TYPE_UNKNOWN = 0; - SOCKET_TYPE_RFCOMM = 1; - SOCKET_TYPE_SCO = 2; - SOCKET_TYPE_L2CAP_BREDR = 3; - SOCKET_TYPE_L2CAP_LE = 4; -} - -enum SocketConnectionstateEnum { - SOCKET_CONNECTION_STATE_UNKNOWN = 0; - // Socket acts as a server waiting for connection - SOCKET_CONNECTION_STATE_LISTENING = 1; - // Socket acts as a client trying to connect - SOCKET_CONNECTION_STATE_CONNECTING = 2; - // Socket is connected - SOCKET_CONNECTION_STATE_CONNECTED = 3; - // Socket tries to disconnect from remote - SOCKET_CONNECTION_STATE_DISCONNECTING = 4; - // This socket is closed - SOCKET_CONNECTION_STATE_DISCONNECTED = 5; -} - -enum SocketRoleEnum { - SOCKET_ROLE_UNKNOWN = 0; - SOCKET_ROLE_LISTEN = 1; - SOCKET_ROLE_CONNECTION = 2; -} diff --git a/core/proto/android/bluetooth/hci/enums.proto b/core/proto/android/bluetooth/hci/enums.proto deleted file mode 100644 index ef894e548351..000000000000 --- a/core/proto/android/bluetooth/hci/enums.proto +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.bluetooth.hci; - -option java_outer_classname = "BluetoothHciProtoEnums"; -option java_multiple_files = true; - -// HCI command opcodes (OCF+OGF) from Bluetooth 5.0 specification Vol 2, Part E, Section 7 -// Original definition: system/bt/stack/include/hcidefs.h -enum CommandEnum { - // Opcode is at most 2 bytes (0xFFFF), thus 0xFFFFF must not be a valid value - CMD_UNKNOWN = 0xFFFFF; - // Link control commands 0x0400 - CMD_INQUIRY = 0x0401; - CMD_INQUIRY_CANCEL = 0x0402; - CMD_PERIODIC_INQUIRY_MODE = 0x0403; - CMD_EXIT_PERIODIC_INQUIRY_MODE = 0x0404; - CMD_CREATE_CONNECTION = 0x0405; - CMD_DISCONNECT = 0x0406; - CMD_ADD_SCO_CONNECTION = 0x0407; // Deprecated since Bluetooth 1.2 - CMD_CREATE_CONNECTION_CANCEL = 0x0408; - CMD_ACCEPT_CONNECTION_REQUEST = 0x0409; - CMD_REJECT_CONNECTION_REQUEST = 0x040A; - CMD_LINK_KEY_REQUEST_REPLY = 0x040B; - CMD_LINK_KEY_REQUEST_NEG_REPLY = 0x040C; - CMD_PIN_CODE_REQUEST_REPLY = 0x040D; - CMD_PIN_CODE_REQUEST_NEG_REPLY = 0x040E; - CMD_CHANGE_CONN_PACKET_TYPE = 0x040F; - CMD_AUTHENTICATION_REQUESTED = 0x0411; - CMD_SET_CONN_ENCRYPTION = 0x0413; - CMD_CHANGE_CONN_LINK_KEY = 0x0415; - CMD_MASTER_LINK_KEY = 0x0417; - CMD_RMT_NAME_REQUEST = 0x0419; - CMD_RMT_NAME_REQUEST_CANCEL = 0x041A; - CMD_READ_RMT_FEATURES = 0x041B; - CMD_READ_RMT_EXT_FEATURES = 0x041C; - CMD_READ_RMT_VERSION_INFO = 0x041D; - CMD_READ_RMT_CLOCK_OFFSET = 0x041F; - CMD_READ_LMP_HANDLE = 0x0420; - CMD_SETUP_ESCO_CONNECTION = 0x0428; - CMD_ACCEPT_ESCO_CONNECTION = 0x0429; - CMD_REJECT_ESCO_CONNECTION = 0x042A; - CMD_IO_CAPABILITY_REQUEST_REPLY = 0x042B; - CMD_USER_CONF_REQUEST_REPLY = 0x042C; - CMD_USER_CONF_VALUE_NEG_REPLY = 0x042D; - CMD_USER_PASSKEY_REQ_REPLY = 0x042E; - CMD_USER_PASSKEY_REQ_NEG_REPLY = 0x042F; - CMD_REM_OOB_DATA_REQ_REPLY = 0x0430; - CMD_REM_OOB_DATA_REQ_NEG_REPLY = 0x0433; - CMD_IO_CAP_REQ_NEG_REPLY = 0x0434; - // BEGIN: AMP commands (not used in system/bt) - CMD_CREATE_PHYSICAL_LINK = 0x0435; - CMD_ACCEPT_PHYSICAL_LINK = 0x0436; - CMD_DISCONNECT_PHYSICAL_LINK = 0x0437; - CMD_CREATE_LOGICAL_LINK = 0x0438; - CMD_ACCEPT_LOGICAL_LINK = 0x0439; - CMD_DISCONNECT_LOGICAL_LINK = 0x043A; - CMD_LOGICAL_LINK_CANCEL = 0x043B; - CMD_FLOW_SPEC_MODIFY = 0x043C; - // END: AMP commands - CMD_ENH_SETUP_ESCO_CONNECTION = 0x043D; - CMD_ENH_ACCEPT_ESCO_CONNECTION = 0x043E; - CMD_TRUNCATED_PAGE = 0x043F; - CMD_TRUNCATED_PAGE_CANCEL = 0x0440; - CMD_SET_CLB = 0x0441; - CMD_RECEIVE_CLB = 0x0442; - CMD_START_SYNC_TRAIN = 0x0443; - CMD_RECEIVE_SYNC_TRAIN = 0x0444; - CMD_REM_OOB_EXTENDED_DATA_REQ_REPLY = 0x0445; // Not currently used in system/bt - // Link policy commands 0x0800 - CMD_HOLD_MODE = 0x0801; - CMD_SNIFF_MODE = 0x0803; - CMD_EXIT_SNIFF_MODE = 0x0804; - CMD_PARK_MODE = 0x0805; - CMD_EXIT_PARK_MODE = 0x0806; - CMD_QOS_SETUP = 0x0807; - CMD_ROLE_DISCOVERY = 0x0809; - CMD_SWITCH_ROLE = 0x080B; - CMD_READ_POLICY_SETTINGS = 0x080C; - CMD_WRITE_POLICY_SETTINGS = 0x080D; - CMD_READ_DEF_POLICY_SETTINGS = 0x080E; - CMD_WRITE_DEF_POLICY_SETTINGS = 0x080F; - CMD_FLOW_SPECIFICATION = 0x0810; - CMD_SNIFF_SUB_RATE = 0x0811; - // Host controller baseband commands 0x0C00 - CMD_SET_EVENT_MASK = 0x0C01; - CMD_RESET = 0x0C03; - CMD_SET_EVENT_FILTER = 0x0C05; - CMD_FLUSH = 0x0C08; - CMD_READ_PIN_TYPE = 0x0C09; - CMD_WRITE_PIN_TYPE = 0x0C0A; - CMD_CREATE_NEW_UNIT_KEY = 0x0C0B; - CMD_GET_MWS_TRANS_LAYER_CFG = 0x0C0C; // Deprecated (not used in spec) - CMD_READ_STORED_LINK_KEY = 0x0C0D; - CMD_WRITE_STORED_LINK_KEY = 0x0C11; - CMD_DELETE_STORED_LINK_KEY = 0x0C12; - CMD_CHANGE_LOCAL_NAME = 0x0C13; - CMD_READ_LOCAL_NAME = 0x0C14; - CMD_READ_CONN_ACCEPT_TOUT = 0x0C15; - CMD_WRITE_CONN_ACCEPT_TOUT = 0x0C16; - CMD_READ_PAGE_TOUT = 0x0C17; - CMD_WRITE_PAGE_TOUT = 0x0C18; - CMD_READ_SCAN_ENABLE = 0x0C19; - CMD_WRITE_SCAN_ENABLE = 0x0C1A; - CMD_READ_PAGESCAN_CFG = 0x0C1B; - CMD_WRITE_PAGESCAN_CFG = 0x0C1C; - CMD_READ_INQUIRYSCAN_CFG = 0x0C1D; - CMD_WRITE_INQUIRYSCAN_CFG = 0x0C1E; - CMD_READ_AUTHENTICATION_ENABLE = 0x0C1F; - CMD_WRITE_AUTHENTICATION_ENABLE = 0x0C20; - CMD_READ_ENCRYPTION_MODE = 0x0C21; // Deprecated - CMD_WRITE_ENCRYPTION_MODE = 0x0C22; // Deprecated - CMD_READ_CLASS_OF_DEVICE = 0x0C23; - CMD_WRITE_CLASS_OF_DEVICE = 0x0C24; - CMD_READ_VOICE_SETTINGS = 0x0C25; - CMD_WRITE_VOICE_SETTINGS = 0x0C26; - CMD_READ_AUTOMATIC_FLUSH_TIMEOUT = 0x0C27; - CMD_WRITE_AUTOMATIC_FLUSH_TIMEOUT = 0x0C28; - CMD_READ_NUM_BCAST_REXMITS = 0x0C29; - CMD_WRITE_NUM_BCAST_REXMITS = 0x0C2A; - CMD_READ_HOLD_MODE_ACTIVITY = 0x0C2B; - CMD_WRITE_HOLD_MODE_ACTIVITY = 0x0C2C; - CMD_READ_TRANSMIT_POWER_LEVEL = 0x0C2D; - CMD_READ_SCO_FLOW_CTRL_ENABLE = 0x0C2E; - CMD_WRITE_SCO_FLOW_CTRL_ENABLE = 0x0C2F; - CMD_SET_HC_TO_HOST_FLOW_CTRL = 0x0C31; - CMD_HOST_BUFFER_SIZE = 0x0C33; - CMD_HOST_NUM_PACKETS_DONE = 0x0C35; - CMD_READ_LINK_SUPER_TOUT = 0x0C36; - CMD_WRITE_LINK_SUPER_TOUT = 0x0C37; - CMD_READ_NUM_SUPPORTED_IAC = 0x0C38; - CMD_READ_CURRENT_IAC_LAP = 0x0C39; - CMD_WRITE_CURRENT_IAC_LAP = 0x0C3A; - CMD_READ_PAGESCAN_PERIOD_MODE = 0x0C3B; // Deprecated - CMD_WRITE_PAGESCAN_PERIOD_MODE = 0x0C3C; // Deprecated - CMD_READ_PAGESCAN_MODE = 0x0C3D; // Deprecated - CMD_WRITE_PAGESCAN_MODE = 0x0C3E; // Deprecated - CMD_SET_AFH_CHANNELS = 0x0C3F; - CMD_READ_INQSCAN_TYPE = 0x0C42; - CMD_WRITE_INQSCAN_TYPE = 0x0C43; - CMD_READ_INQUIRY_MODE = 0x0C44; - CMD_WRITE_INQUIRY_MODE = 0x0C45; - CMD_READ_PAGESCAN_TYPE = 0x0C46; - CMD_WRITE_PAGESCAN_TYPE = 0x0C47; - CMD_READ_AFH_ASSESSMENT_MODE = 0x0C48; - CMD_WRITE_AFH_ASSESSMENT_MODE = 0x0C49; - CMD_READ_EXT_INQ_RESPONSE = 0x0C51; - CMD_WRITE_EXT_INQ_RESPONSE = 0x0C52; - CMD_REFRESH_ENCRYPTION_KEY = 0x0C53; - CMD_READ_SIMPLE_PAIRING_MODE = 0x0C55; - CMD_WRITE_SIMPLE_PAIRING_MODE = 0x0C56; - CMD_READ_LOCAL_OOB_DATA = 0x0C57; - CMD_READ_INQ_TX_POWER_LEVEL = 0x0C58; - CMD_WRITE_INQ_TX_POWER_LEVEL = 0x0C59; - CMD_READ_ERRONEOUS_DATA_RPT = 0x0C5A; - CMD_WRITE_ERRONEOUS_DATA_RPT = 0x0C5B; - CMD_ENHANCED_FLUSH = 0x0C5F; - CMD_SEND_KEYPRESS_NOTIF = 0x0C60; - CMD_READ_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0C61; - CMD_WRITE_LOGICAL_LINK_ACCEPT_TIMEOUT = 0x0C62; - CMD_SET_EVENT_MASK_PAGE_2 = 0x0C63; - CMD_READ_LOCATION_DATA = 0x0C64; - CMD_WRITE_LOCATION_DATA = 0x0C65; - CMD_READ_FLOW_CONTROL_MODE = 0x0C66; - CMD_WRITE_FLOW_CONTROL_MODE = 0x0C67; - CMD_READ_ENHANCED_TX_PWR_LEVEL = 0x0C68; // Not currently used in system/bt - CMD_READ_BE_FLUSH_TOUT = 0x0C69; - CMD_WRITE_BE_FLUSH_TOUT = 0x0C6A; - CMD_SHORT_RANGE_MODE = 0x0C6B; - CMD_READ_BLE_HOST_SUPPORT = 0x0C6C; - CMD_WRITE_BLE_HOST_SUPPORT = 0x0C6D; - CMD_SET_MWS_CHANNEL_PARAMETERS = 0x0C6E; - CMD_SET_EXTERNAL_FRAME_CONFIGURATION = 0x0C6F; - CMD_SET_MWS_SIGNALING = 0x0C70; - CMD_SET_MWS_TRANSPORT_LAYER = 0x0C71; - CMD_SET_MWS_SCAN_FREQUENCY_TABLE = 0x0C72; - CMD_SET_MWS_PATTERN_CONFIGURATION = 0x0C73; - CMD_SET_RESERVED_LT_ADDR = 0x0C74; - CMD_DELETE_RESERVED_LT_ADDR = 0x0C75; - CMD_WRITE_CLB_DATA = 0x0C76; - CMD_READ_SYNC_TRAIN_PARAM = 0x0C77; - CMD_WRITE_SYNC_TRAIN_PARAM = 0x0C78; - CMD_READ_SECURE_CONNS_SUPPORT = 0x0C79; - CMD_WRITE_SECURE_CONNS_SUPPORT = 0x0C7A; - CMD_READ_AUTHED_PAYLOAD_TIMEOUT = 0x0C7B; // Not currently used in system/bt - CMD_WRITE_AUTHED_PAYLOAD_TIMEOUT = 0x0C7C; // Not currently used in system/bt - CMD_READ_LOCAL_OOB_EXTENDED_DATA = 0x0C7D; // Not currently used in system/bt - CMD_READ_EXTENDED_PAGE_TIMEOUT = 0x0C7E; // Not currently used in system/bt - CMD_WRITE_EXTENDED_PAGE_TIMEOUT = 0x0C7F; // Not currently used in system/bt - CMD_READ_EXTENDED_INQUIRY_LENGTH = 0x0C80; // Not currently used in system/bt - CMD_WRITE_EXTENDED_INQUIRY_LENGTH = 0x0C81; // Not currently used in system/bt - // Informational parameter commands 0x1000 - CMD_READ_LOCAL_VERSION_INFO = 0x1001; - CMD_READ_LOCAL_SUPPORTED_CMDS = 0x1002; - CMD_READ_LOCAL_FEATURES = 0x1003; - CMD_READ_LOCAL_EXT_FEATURES = 0x1004; - CMD_READ_BUFFER_SIZE = 0x1005; - CMD_READ_COUNTRY_CODE = 0x1007; // Deprecated - CMD_READ_BD_ADDR = 0x1009; - CMD_READ_DATA_BLOCK_SIZE = 0x100A; - CMD_READ_LOCAL_SUPPORTED_CODECS = 0x100B; - // Status parameter commands 0x1400 - CMD_READ_FAILED_CONTACT_COUNTER = 0x1401; - CMD_RESET_FAILED_CONTACT_COUNTER = 0x1402; - CMD_GET_LINK_QUALITY = 0x1403; - CMD_READ_RSSI = 0x1405; - CMD_READ_AFH_CH_MAP = 0x1406; - CMD_READ_CLOCK = 0x1407; - CMD_READ_ENCR_KEY_SIZE = 0x1408; - CMD_READ_LOCAL_AMP_INFO = 0x1409; - CMD_READ_LOCAL_AMP_ASSOC = 0x140A; - CMD_WRITE_REMOTE_AMP_ASSOC = 0x140B; - CMD_GET_MWS_TRANSPORT_CFG = 0x140C; // Not currently used in system/bt - CMD_SET_TRIGGERED_CLK_CAPTURE = 0x140D; // Not currently used in system/bt - // Testing commands 0x1800 - CMD_READ_LOOPBACK_MODE = 0x1801; - CMD_WRITE_LOOPBACK_MODE = 0x1802; - CMD_ENABLE_DEV_UNDER_TEST_MODE = 0x1803; - CMD_WRITE_SIMP_PAIR_DEBUG_MODE = 0x1804; - CMD_ENABLE_AMP_RCVR_REPORTS = 0x1807; - CMD_AMP_TEST_END = 0x1808; - CMD_AMP_TEST = 0x1809; - CMD_WRITE_SECURE_CONN_TEST_MODE = 0x180A; // Not currently used in system/bt - // BLE commands 0x2000 - CMD_BLE_SET_EVENT_MASK = 0x2001; - CMD_BLE_READ_BUFFER_SIZE = 0x2002; - CMD_BLE_READ_LOCAL_SPT_FEAT = 0x2003; - CMD_BLE_WRITE_LOCAL_SPT_FEAT = 0x2004; - CMD_BLE_WRITE_RANDOM_ADDR = 0x2005; - CMD_BLE_WRITE_ADV_PARAMS = 0x2006; - CMD_BLE_READ_ADV_CHNL_TX_POWER = 0x2007; - CMD_BLE_WRITE_ADV_DATA = 0x2008; - CMD_BLE_WRITE_SCAN_RSP_DATA = 0x2009; - CMD_BLE_WRITE_ADV_ENABLE = 0x200A; - CMD_BLE_WRITE_SCAN_PARAMS = 0x200B; - CMD_BLE_WRITE_SCAN_ENABLE = 0x200C; - CMD_BLE_CREATE_LL_CONN = 0x200D; - CMD_BLE_CREATE_CONN_CANCEL = 0x200E; - CMD_BLE_READ_WHITE_LIST_SIZE = 0x200F; - CMD_BLE_CLEAR_WHITE_LIST = 0x2010; - CMD_BLE_ADD_WHITE_LIST = 0x2011; - CMD_BLE_REMOVE_WHITE_LIST = 0x2012; - CMD_BLE_UPD_LL_CONN_PARAMS = 0x2013; - CMD_BLE_SET_HOST_CHNL_CLASS = 0x2014; - CMD_BLE_READ_CHNL_MAP = 0x2015; - CMD_BLE_READ_REMOTE_FEAT = 0x2016; - CMD_BLE_ENCRYPT = 0x2017; - CMD_BLE_RAND = 0x2018; - CMD_BLE_START_ENC = 0x2019; - CMD_BLE_LTK_REQ_REPLY = 0x201A; - CMD_BLE_LTK_REQ_NEG_REPLY = 0x201B; - CMD_BLE_READ_SUPPORTED_STATES = 0x201C; - CMD_BLE_RECEIVER_TEST = 0x201D; - CMD_BLE_TRANSMITTER_TEST = 0x201E; - CMD_BLE_TEST_END = 0x201F; - CMD_BLE_RC_PARAM_REQ_REPLY = 0x2020; - CMD_BLE_RC_PARAM_REQ_NEG_REPLY = 0x2021; - CMD_BLE_SET_DATA_LENGTH = 0x2022; - CMD_BLE_READ_DEFAULT_DATA_LENGTH = 0x2023; - CMD_BLE_WRITE_DEFAULT_DATA_LENGTH = 0x2024; - CMD_BLE_GENERATE_DHKEY = 0x2026; // Not currently used in system/bt - CMD_BLE_ADD_DEV_RESOLVING_LIST = 0x2027; - CMD_BLE_RM_DEV_RESOLVING_LIST = 0x2028; - CMD_BLE_CLEAR_RESOLVING_LIST = 0x2029; - CMD_BLE_READ_RESOLVING_LIST_SIZE = 0x202A; - CMD_BLE_READ_RESOLVABLE_ADDR_PEER = 0x202B; - CMD_BLE_READ_RESOLVABLE_ADDR_LOCAL = 0x202C; - CMD_BLE_SET_ADDR_RESOLUTION_ENABLE = 0x202D; - CMD_BLE_SET_RAND_PRIV_ADDR_TIMOUT = 0x202E; - CMD_BLE_READ_MAXIMUM_DATA_LENGTH = 0x202F; - CMD_BLE_READ_PHY = 0x2030; - CMD_BLE_SET_DEFAULT_PHY = 0x2031; - CMD_BLE_SET_PHY = 0x2032; - CMD_BLE_ENH_RECEIVER_TEST = 0x2033; - CMD_BLE_ENH_TRANSMITTER_TEST = 0x2034; - CMD_BLE_SET_EXT_ADVERTISING_RANDOM_ADDRESS = 0x2035; - CMD_BLE_SET_EXT_ADVERTISING_PARAM = 0x2036; - CMD_BLE_SET_EXT_ADVERTISING_DATA = 0x2037; - CMD_BLE_SET_EXT_ADVERTISING_SCAN_RESP = 0x2038; - CMD_BLE_SET_EXT_ADVERTISING_ENABLE = 0x2039; - CMD_BLE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH = 0x203A; - CMD_BLE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS = 0x203B; - CMD_BLE_REMOVE_ADVERTISING_SET = 0x203C; - CMD_BLE_CLEAR_ADVERTISING_SETS = 0x203D; - CMD_BLE_SET_PERIODIC_ADVERTISING_PARAM = 0x203E; - CMD_BLE_SET_PERIODIC_ADVERTISING_DATA = 0x203F; - CMD_BLE_SET_PERIODIC_ADVERTISING_ENABLE = 0x2040; - CMD_BLE_SET_EXTENDED_SCAN_PARAMETERS = 0x2041; - CMD_BLE_SET_EXTENDED_SCAN_ENABLE = 0x2042; - CMD_BLE_EXTENDED_CREATE_CONNECTION = 0x2043; - CMD_BLE_PERIODIC_ADVERTISING_CREATE_SYNC = 0x2044; - CMD_BLE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL = 0x2045; - CMD_BLE_PERIODIC_ADVERTISING_TERMINATE_SYNC = 0x2046; - CMD_BLE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST = 0x2047; - CMD_BLE_RM_DEVICE_FROM_PERIODIC_ADVERTISING_LIST = 0x2048; - CMD_BLE_CLEAR_PERIODIC_ADVERTISING_LIST = 0x2049; - CMD_BLE_READ_PERIODIC_ADVERTISING_LIST_SIZE = 0x204A; - CMD_BLE_READ_TRANSMIT_POWER = 0x204B; - CMD_BLE_READ_RF_COMPENS_POWER = 0x204C; - CMD_BLE_WRITE_RF_COMPENS_POWER = 0x204D; - CMD_BLE_SET_PRIVACY_MODE = 0x204E; - // Vendor specific commands 0xFC00 and above - // Android vendor specific commands defined in - // https://source.android.com/devices/bluetooth/hci_requirements#vendor-specific-capabilities - CMD_BLE_VENDOR_CAP = 0xFD53; - CMD_BLE_MULTI_ADV = 0xFD54; - CMD_BLE_BATCH_SCAN = 0xFD56; - CMD_BLE_ADV_FILTER = 0xFD57; - CMD_BLE_TRACK_ADV = 0xFD58; - CMD_BLE_ENERGY_INFO = 0xFD59; - CMD_BLE_EXTENDED_SCAN_PARAMS = 0xFD5A; - CMD_CONTROLLER_DEBUG_INFO = 0xFD5B; - CMD_CONTROLLER_A2DP_OPCODE = 0xFD5D; - CMD_BRCM_SET_ACL_PRIORITY = 0xFC57; - // Other vendor specific commands below here -} - -// HCI event codes from the Bluetooth 5.0 specification Vol 2, Part 7, Section 7 -// Original definition: system/bt/stack/include/hcidefs.h -enum EventEnum { - // Event is at most 1 byte (0xFF), thus 0xFFF must not be a valid value - EVT_UNKNOWN = 0xFFF; - EVT_INQUIRY_COMP = 0x01; - EVT_INQUIRY_RESULT = 0x02; - EVT_CONNECTION_COMP = 0x03; - EVT_CONNECTION_REQUEST = 0x04; - EVT_DISCONNECTION_COMP = 0x05; - EVT_AUTHENTICATION_COMP = 0x06; - EVT_RMT_NAME_REQUEST_COMP = 0x07; - EVT_ENCRYPTION_CHANGE = 0x08; - EVT_CHANGE_CONN_LINK_KEY = 0x09; - EVT_MASTER_LINK_KEY_COMP = 0x0A; - EVT_READ_RMT_FEATURES_COMP = 0x0B; - EVT_READ_RMT_VERSION_COMP = 0x0C; - EVT_QOS_SETUP_COMP = 0x0D; - EVT_COMMAND_COMPLETE = 0x0E; - EVT_COMMAND_STATUS = 0x0F; - EVT_HARDWARE_ERROR = 0x10; - EVT_FLUSH_OCCURRED = 0x11; - EVT_ROLE_CHANGE = 0x12; - EVT_NUM_COMPL_DATA_PKTS = 0x13; - EVT_MODE_CHANGE = 0x14; - EVT_RETURN_LINK_KEYS = 0x15; - EVT_PIN_CODE_REQUEST = 0x16; - EVT_LINK_KEY_REQUEST = 0x17; - EVT_LINK_KEY_NOTIFICATION = 0x18; - EVT_LOOPBACK_COMMAND = 0x19; - EVT_DATA_BUF_OVERFLOW = 0x1A; - EVT_MAX_SLOTS_CHANGED = 0x1B; - EVT_READ_CLOCK_OFF_COMP = 0x1C; - EVT_CONN_PKT_TYPE_CHANGE = 0x1D; - EVT_QOS_VIOLATION = 0x1E; - EVT_PAGE_SCAN_MODE_CHANGE = 0x1F; // Deprecated - EVT_PAGE_SCAN_REP_MODE_CHNG = 0x20; - EVT_FLOW_SPECIFICATION_COMP = 0x21; - EVT_INQUIRY_RSSI_RESULT = 0x22; - EVT_READ_RMT_EXT_FEATURES_COMP = 0x23; - EVT_ESCO_CONNECTION_COMP = 0x2C; - EVT_ESCO_CONNECTION_CHANGED = 0x2D; - EVT_SNIFF_SUB_RATE = 0x2E; - EVT_EXTENDED_INQUIRY_RESULT = 0x2F; - EVT_ENCRYPTION_KEY_REFRESH_COMP = 0x30; - EVT_IO_CAPABILITY_REQUEST = 0x31; - EVT_IO_CAPABILITY_RESPONSE = 0x32; - EVT_USER_CONFIRMATION_REQUEST = 0x33; - EVT_USER_PASSKEY_REQUEST = 0x34; - EVT_REMOTE_OOB_DATA_REQUEST = 0x35; - EVT_SIMPLE_PAIRING_COMPLETE = 0x36; - EVT_LINK_SUPER_TOUT_CHANGED = 0x38; - EVT_ENHANCED_FLUSH_COMPLETE = 0x39; - EVT_USER_PASSKEY_NOTIFY = 0x3B; - EVT_KEYPRESS_NOTIFY = 0x3C; - EVT_RMT_HOST_SUP_FEAT_NOTIFY = 0x3D; - EVT_BLE_META = 0x3E; - EVT_PHYSICAL_LINK_COMP = 0x40; - EVT_CHANNEL_SELECTED = 0x41; - EVT_DISC_PHYSICAL_LINK_COMP = 0x42; - EVT_PHY_LINK_LOSS_EARLY_WARNING = 0x43; - EVT_PHY_LINK_RECOVERY = 0x44; - EVT_LOGICAL_LINK_COMP = 0x45; - EVT_DISC_LOGICAL_LINK_COMP = 0x46; - EVT_FLOW_SPEC_MODIFY_COMP = 0x47; - EVT_NUM_COMPL_DATA_BLOCKS = 0x48; - EVT_AMP_TEST_START = 0x49; // Not currently used in system/bt - EVT_AMP_TEST_END = 0x4A; // Not currently used in system/bt - EVT_AMP_RECEIVER_RPT = 0x4B; // Not currently used in system/bt - EVT_SHORT_RANGE_MODE_COMPLETE = 0x4C; - EVT_AMP_STATUS_CHANGE = 0x4D; - EVT_SET_TRIGGERED_CLOCK_CAPTURE = 0x4E; - EVT_SYNC_TRAIN_CMPL = 0x4F; // Not currently used in system/bt - EVT_SYNC_TRAIN_RCVD = 0x50; // Not currently used in system/bt - EVT_CONNLESS_SLAVE_BROADCAST_RCVD = 0x51; // Not currently used in system/bt - EVT_CONNLESS_SLAVE_BROADCAST_TIMEOUT = 0x52; // Not currently used in system/bt - EVT_TRUNCATED_PAGE_CMPL = 0x53; // Not currently used in system/bt - EVT_SLAVE_PAGE_RES_TIMEOUT = 0x54; // Not currently used in system/bt - EVT_CONNLESS_SLAVE_BROADCAST_CHNL_MAP_CHANGE = 0x55; // Not currently used in system/bt - EVT_INQUIRY_RES_NOTIFICATION = 0x56; // Not currently used in system/bt - EVT_AUTHED_PAYLOAD_TIMEOUT = 0x57; // Not currently used in system/bt - EVT_SAM_STATUS_CHANGE = 0x58; // Not currently used in system/bt -} - -// Bluetooth low energy related meta event codes -// from the Bluetooth 5.0 specification Vol 2, Part E, Section 7.7.65 -// Original definition: system/bt/stack/include/hcidefs.h -enum BleMetaEventEnum { - // BLE meta event code is at most 1 byte (0xFF), thus 0xFFF must not be a valid value - BLE_EVT_UNKNOWN = 0xFFF; - BLE_EVT_CONN_COMPLETE_EVT = 0x01; - BLE_EVT_ADV_PKT_RPT_EVT = 0x02; - BLE_EVT_LL_CONN_PARAM_UPD_EVT = 0x03; - BLE_EVT_READ_REMOTE_FEAT_CMPL_EVT = 0x04; - BLE_EVT_LTK_REQ_EVT = 0x05; - BLE_EVT_RC_PARAM_REQ_EVT = 0x06; - BLE_EVT_DATA_LENGTH_CHANGE_EVT = 0x07; - BLE_EVT_READ_LOCAL_P256_PUB_KEY = 0x08; // Not currently used in system/bt - BLE_EVT_GEN_DHKEY_CMPL = 0x09; // Not currently used in system/bt - BLE_EVT_ENHANCED_CONN_COMPLETE_EVT = 0x0a; - BLE_EVT_DIRECT_ADV_EVT = 0x0b; - BLE_EVT_PHY_UPDATE_COMPLETE_EVT = 0x0c; - BLE_EVT_EXTENDED_ADVERTISING_REPORT_EVT = 0x0D; - BLE_EVT_PERIODIC_ADV_SYNC_EST_EVT = 0x0E; - BLE_EVT_PERIODIC_ADV_REPORT_EVT = 0x0F; - BLE_EVT_PERIODIC_ADV_SYNC_LOST_EVT = 0x10; - BLE_EVT_SCAN_TIMEOUT_EVT = 0x11; - BLE_EVT_ADVERTISING_SET_TERMINATED_EVT = 0x12; - BLE_EVT_SCAN_REQ_RX_EVT = 0x13; - BLE_EVT_CHNL_SELECTION_ALGORITHM = 0x14; // Not currently used in system/bt -} - -// HCI status code from the Bluetooth 5.0 specification Vol 2, Part D. -// Original definition: system/bt/stack/include/hcidefs.h -enum StatusEnum { - // Status is at most 1 byte (0xFF), thus 0xFFF must not be a valid value - STATUS_UNKNOWN = 0xFFF; - STATUS_SUCCESS = 0x00; - STATUS_ILLEGAL_COMMAND = 0x01; - STATUS_NO_CONNECTION = 0x02; - STATUS_HW_FAILURE = 0x03; - STATUS_PAGE_TIMEOUT = 0x04; - STATUS_AUTH_FAILURE = 0x05; - STATUS_KEY_MISSING = 0x06; - STATUS_MEMORY_FULL = 0x07; - STATUS_CONNECTION_TOUT = 0x08; - STATUS_MAX_NUM_OF_CONNECTIONS = 0x09; - STATUS_MAX_NUM_OF_SCOS = 0x0A; - STATUS_CONNECTION_EXISTS = 0x0B; - STATUS_COMMAND_DISALLOWED = 0x0C; - STATUS_HOST_REJECT_RESOURCES = 0x0D; - STATUS_HOST_REJECT_SECURITY = 0x0E; - STATUS_HOST_REJECT_DEVICE = 0x0F; - STATUS_HOST_TIMEOUT = 0x10; - STATUS_UNSUPPORTED_VALUE = 0x11; - STATUS_ILLEGAL_PARAMETER_FMT = 0x12; - STATUS_PEER_USER = 0x13; - STATUS_PEER_LOW_RESOURCES = 0x14; - STATUS_PEER_POWER_OFF = 0x15; - STATUS_CONN_CAUSE_LOCAL_HOST = 0x16; - STATUS_REPEATED_ATTEMPTS = 0x17; - STATUS_PAIRING_NOT_ALLOWED = 0x18; - STATUS_UNKNOWN_LMP_PDU = 0x19; - STATUS_UNSUPPORTED_REM_FEATURE = 0x1A; - STATUS_SCO_OFFSET_REJECTED = 0x1B; - STATUS_SCO_INTERVAL_REJECTED = 0x1C; - STATUS_SCO_AIR_MODE = 0x1D; - STATUS_INVALID_LMP_PARAM = 0x1E; - STATUS_UNSPECIFIED = 0x1F; - STATUS_UNSUPPORTED_LMP_FEATURE = 0x20; - STATUS_ROLE_CHANGE_NOT_ALLOWED = 0x21; - STATUS_LMP_RESPONSE_TIMEOUT = 0x22; - STATUS_LMP_STATUS_TRANS_COLLISION = 0x23; - STATUS_LMP_PDU_NOT_ALLOWED = 0x24; - STATUS_ENCRY_MODE_NOT_ACCEPTABLE = 0x25; - STATUS_UNIT_KEY_USED = 0x26; - STATUS_QOS_NOT_SUPPORTED = 0x27; - STATUS_INSTANT_PASSED = 0x28; - STATUS_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED = 0x29; - STATUS_DIFF_TRANSACTION_COLLISION = 0x2A; - STATUS_UNDEFINED_0x2B = 0x2B; // Not used - STATUS_QOS_UNACCEPTABLE_PARAM = 0x2C; - STATUS_QOS_REJECTED = 0x2D; - STATUS_CHAN_CLASSIF_NOT_SUPPORTED = 0x2E; - STATUS_INSUFFCIENT_SECURITY = 0x2F; - STATUS_PARAM_OUT_OF_RANGE = 0x30; - STATUS_UNDEFINED_0x31 = 0x31; // Not used - STATUS_ROLE_SWITCH_PENDING = 0x32; - STATUS_UNDEFINED_0x33 = 0x33; - STATUS_RESERVED_SLOT_VIOLATION = 0x34; - STATUS_ROLE_SWITCH_FAILED = 0x35; - STATUS_INQ_RSP_DATA_TOO_LARGE = 0x36; - STATUS_SIMPLE_PAIRING_NOT_SUPPORTED = 0x37; - STATUS_HOST_BUSY_PAIRING = 0x38; - STATUS_REJ_NO_SUITABLE_CHANNEL = 0x39; - STATUS_CONTROLLER_BUSY = 0x3A; - STATUS_UNACCEPT_CONN_INTERVAL = 0x3B; - STATUS_ADVERTISING_TIMEOUT = 0x3C; - STATUS_CONN_TOUT_DUE_TO_MIC_FAILURE = 0x3D; - STATUS_CONN_FAILED_ESTABLISHMENT = 0x3E; - STATUS_MAC_CONNECTION_FAILED = 0x3F; - STATUS_LT_ADDR_ALREADY_IN_USE = 0x40; - STATUS_LT_ADDR_NOT_ALLOCATED = 0x41; - STATUS_CLB_NOT_ENABLED = 0x42; - STATUS_CLB_DATA_TOO_BIG = 0x43; - STATUS_OPERATION_CANCELED_BY_HOST = 0x44; // Not currently used in system/bt -} - -enum BqrIdEnum { - BQR_ID_UNKNOWN = 0x00; - BQR_ID_MONITOR_MODE = 0x01; - BQR_ID_APPROACH_LSTO = 0x02; - BQR_ID_A2DP_AUDIO_CHOPPY = 0x03; - BQR_ID_SCO_VOICE_CHOPPY = 0x04; -} - -enum BqrPacketTypeEnum { - BQR_PACKET_TYPE_UNKNOWN = 0x00; - BQR_PACKET_TYPE_ID = 0x01; - BQR_PACKET_TYPE_NULL = 0x02; - BQR_PACKET_TYPE_POLL = 0x03; - BQR_PACKET_TYPE_FHS = 0x04; - BQR_PACKET_TYPE_HV1 = 0x05; - BQR_PACKET_TYPE_HV2 = 0x06; - BQR_PACKET_TYPE_HV3 = 0x07; - BQR_PACKET_TYPE_DV = 0x08; - BQR_PACKET_TYPE_EV3 = 0x09; - BQR_PACKET_TYPE_EV4 = 0x0A; - BQR_PACKET_TYPE_EV5 = 0x0B; - BQR_PACKET_TYPE_2EV3 = 0x0C; - BQR_PACKET_TYPE_2EV5 = 0x0D; - BQR_PACKET_TYPE_3EV3 = 0x0E; - BQR_PACKET_TYPE_3EV5 = 0x0F; - BQR_PACKET_TYPE_DM1 = 0x10; - BQR_PACKET_TYPE_DH1 = 0x11; - BQR_PACKET_TYPE_DM3 = 0x12; - BQR_PACKET_TYPE_DH3 = 0x13; - BQR_PACKET_TYPE_DM5 = 0x14; - BQR_PACKET_TYPE_DH5 = 0x15; - BQR_PACKET_TYPE_AUX1 = 0x16; - BQR_PACKET_TYPE_2DH1 = 0x17; - BQR_PACKET_TYPE_2DH3 = 0x18; - BQR_PACKET_TYPE_2DH5 = 0x19; - BQR_PACKET_TYPE_3DH1 = 0x1A; - BQR_PACKET_TYPE_3DH3 = 0x1B; - BQR_PACKET_TYPE_3DH5 = 0x1C; -} diff --git a/core/proto/android/bluetooth/smp/enums.proto b/core/proto/android/bluetooth/smp/enums.proto deleted file mode 100644 index c6747b78dc29..000000000000 --- a/core/proto/android/bluetooth/smp/enums.proto +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019 The Android Open 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. - */ - -syntax = "proto2"; -package android.bluetooth.smp; - -option java_outer_classname = "BluetoothSmpProtoEnums"; -option java_multiple_files = true; - -// SMP Pairing command codes -enum CommandEnum { - CMD_UNKNOWN = 0x00; - CMD_PAIRING_REQUEST = 0x01; - CMD_PAIRING_RESPONSE = 0x02; - CMD_PAIRING_CONFIRM = 0x03; - CMD_PAIRING_RANDOM = 0x04; - CMD_PAIRING_FAILED = 0x05; - CMD_ENCRYPTION_INFON = 0x06; - CMD_MASTER_IDENTIFICATION = 0x07; - CMD_IDENTITY_INFO = 0x08; - CMD_IDENTITY_ADDR_INFO = 0x09; - CMD_SIGNING_INFO = 0x0A; - CMD_SECURITY_REQUEST = 0x0B; - CMD_PAIRING_PUBLIC_KEY = 0x0C; - CMD_PAIRING_DHKEY_CHECK = 0x0D; - CMD_PAIRING_KEYPRESS_INFO = 0x0E; -} - -enum PairingFailReasonEnum { - PAIRING_FAIL_REASON_RESERVED = 0x00; - PAIRING_FAIL_REASON_PASSKEY_ENTRY = 0x01; - PAIRING_FAIL_REASON_OOB = 0x02; - PAIRING_FAIL_REASON_AUTH_REQ = 0x03; - PAIRING_FAIL_REASON_CONFIRM_VALUE = 0x04; - PAIRING_FAIL_REASON_PAIR_NOT_SUPPORT = 0x05; - PAIRING_FAIL_REASON_ENC_KEY_SIZE = 0x06; - PAIRING_FAIL_REASON_INVALID_CMD = 0x07; - PAIRING_FAIL_REASON_UNSPECIFIED = 0x08; - PAIRING_FAIL_REASON_REPEATED_ATTEMPTS = 0x09; - PAIRING_FAIL_REASON_INVALID_PARAMETERS = 0x0A; - PAIRING_FAIL_REASON_DHKEY_CHK = 0x0B; - PAIRING_FAIL_REASON_NUMERIC_COMPARISON = 0x0C; - PAIRING_FAIL_REASON_CLASSIC_PAIRING_IN_PROGR = 0x0D; - PAIRING_FAIL_REASON_XTRANS_DERIVE_NOT_ALLOW = 0x0E; -}
\ No newline at end of file diff --git a/core/proto/android/debug/enums.proto b/core/proto/android/debug/enums.proto deleted file mode 100644 index 6747bb7276b3..000000000000 --- a/core/proto/android/debug/enums.proto +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; -package android.debug; - -option java_outer_classname = "AdbProtoEnums"; -option java_multiple_files = true; - -/** - * adb connection state used to track adb connection changes in AdbDebuggingManager.java. - */ -enum AdbConnectionStateEnum { - UNKNOWN = 0; - - /** - * The adb connection is waiting for approval from the user. - */ - AWAITING_USER_APPROVAL = 1; - - /** - * The user allowed the adb connection from the system. - */ - USER_ALLOWED = 2; - - /** - * The user denied the adb connection from the system. - */ - USER_DENIED = 3; - - /** - * The adb connection was automatically allowed without user interaction due to the system - * being previously allowed by the user with the 'always allow' option selected, and the adb - * grant has not yet expired. - */ - AUTOMATICALLY_ALLOWED = 4; - - /** - * An empty or invalid base64 encoded key was provided to the framework; the connection was - * automatically denied. - */ - DENIED_INVALID_KEY = 5; - - /** - * vold decrypt has not yet occurred; the connection was automatically denied. - */ - DENIED_VOLD_DECRYPT = 6; - - /** - * The adb session has been disconnected. - */ - DISCONNECTED = 7; -} - diff --git a/core/proto/android/hardware/biometrics/enums.proto b/core/proto/android/hardware/biometrics/enums.proto deleted file mode 100644 index f2e06383b5b1..000000000000 --- a/core/proto/android/hardware/biometrics/enums.proto +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; - -package android.hardware.biometrics; - -option java_outer_classname = "BiometricsProtoEnums"; -option java_multiple_files = true; - -// Logging constants for <Biometric>Service and BiometricService - -enum ModalityEnum { - MODALITY_UNKNOWN = 0; - MODALITY_FINGERPRINT = 1; // 1 << 0 - MODALITY_IRIS = 2; // 1 << 1 - MODALITY_FACE = 4; // 1 << 2 -} - -enum ClientEnum { - CLIENT_UNKNOWN = 0; - CLIENT_KEYGUARD = 1; - CLIENT_BIOMETRIC_PROMPT = 2; - CLIENT_FINGERPRINT_MANAGER = 3; // Deprecated API before BiometricPrompt was introduced -} - -enum ActionEnum { - ACTION_UNKNOWN = 0; - ACTION_ENROLL = 1; - ACTION_AUTHENTICATE = 2; - ACTION_ENUMERATE = 3; - ACTION_REMOVE = 4; -} - -enum IssueEnum { - ISSUE_UNKNOWN = 0; - // When a biometric HAL has crashed. - ISSUE_HAL_DEATH = 1; - // When Android Framework has a template that doesn't exist in the HAL. The framework - // is expected to remove its template to stay in sync with the HAL. - ISSUE_UNKNOWN_TEMPLATE_ENROLLED_FRAMEWORK = 2; - // When the HAL has a template that doesn't exist in Android Framework. The framework - // is expected to notify the HAL to remove this template to stay in sync with the framework. - ISSUE_UNKNOWN_TEMPLATE_ENROLLED_HAL = 3; - // When the HAL has not sent ERROR_CANCELED within the specified timeout. - ISSUE_CANCEL_TIMED_OUT = 4; -}
\ No newline at end of file diff --git a/core/proto/android/hardware/sensor/assist/enums.proto b/core/proto/android/hardware/sensor/assist/enums.proto deleted file mode 100644 index 012dcb2e937e..000000000000 --- a/core/proto/android/hardware/sensor/assist/enums.proto +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; -package android.hardware.sensor.assist; - -option java_outer_classname = "AssistGestureProtoEnums"; -option java_multiple_files = true; - -enum AssistGestureStageEnum { - ASSIST_GESTURE_STAGE_UNKNOWN = 0; - ASSIST_GESTURE_STAGE_PROGRESS = 1; - ASSIST_GESTURE_STAGE_PRIMED = 2; - ASSIST_GESTURE_STAGE_DETECTED = 3; -} - -enum AssistGestureFeedbackEnum { - ASSIST_GESTURE_FEEDBACK_UNKNOWN = 0; - ASSIST_GESTURE_FEEDBACK_NOT_USED = 1; - ASSIST_GESTURE_FEEDBACK_USED = 2; -}
\ No newline at end of file diff --git a/core/proto/android/net/networkcapabilities.proto b/core/proto/android/net/networkcapabilities.proto deleted file mode 100644 index be0cad18a24d..000000000000 --- a/core/proto/android/net/networkcapabilities.proto +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.net; - -option java_multiple_files = true; - -import "frameworks/base/core/proto/android/privacy.proto"; - -/** - * An android.net.NetworkCapabilities object. - */ -message NetworkCapabilitiesProto { - option (.android.msg_privacy).dest = DEST_AUTOMATIC; - - enum Transport { - // Indicates this network uses a Cellular transport. - TRANSPORT_CELLULAR = 0; - // Indicates this network uses a Wi-Fi transport. - TRANSPORT_WIFI = 1; - // Indicates this network uses a Bluetooth transport. - TRANSPORT_BLUETOOTH = 2; - // Indicates this network uses an Ethernet transport. - TRANSPORT_ETHERNET = 3; - // Indicates this network uses a VPN transport. - TRANSPORT_VPN = 4; - // Indicates this network uses a Wi-Fi Aware transport. - TRANSPORT_WIFI_AWARE = 5; - // Indicates this network uses a LoWPAN transport. - TRANSPORT_LOWPAN = 6; - } - repeated Transport transports = 1; - - enum NetCapability { - // Indicates this is a network that has the ability to reach the - // carrier's MMSC for sending and receiving MMS messages. - NET_CAPABILITY_MMS = 0; - // Indicates this is a network that has the ability to reach the - // carrier's SUPL server, used to retrieve GPS information. - NET_CAPABILITY_SUPL = 1; - // Indicates this is a network that has the ability to reach the - // carrier's DUN or tethering gateway. - NET_CAPABILITY_DUN = 2; - // Indicates this is a network that has the ability to reach the - // carrier's FOTA portal, used for over the air updates. - NET_CAPABILITY_FOTA = 3; - // Indicates this is a network that has the ability to reach the - // carrier's IMS servers, used for network registration and signaling. - NET_CAPABILITY_IMS = 4; - // Indicates this is a network that has the ability to reach the - // carrier's CBS servers, used for carrier specific services. - NET_CAPABILITY_CBS = 5; - // Indicates this is a network that has the ability to reach a Wi-Fi - // direct peer. - NET_CAPABILITY_WIFI_P2P = 6; - // Indicates this is a network that has the ability to reach a carrier's - // Initial Attach servers. - NET_CAPABILITY_IA = 7; - // Indicates this is a network that has the ability to reach a carrier's - // RCS servers, used for Rich Communication Services. - NET_CAPABILITY_RCS = 8; - // Indicates this is a network that has the ability to reach a carrier's - // XCAP servers, used for configuration and control. - NET_CAPABILITY_XCAP = 9; - // Indicates this is a network that has the ability to reach a carrier's - // Emergency IMS servers or other services, used for network signaling - // during emergency calls. - NET_CAPABILITY_EIMS = 10; - // Indicates that this network is unmetered. - NET_CAPABILITY_NOT_METERED = 11; - // Indicates that this network should be able to reach the internet. - NET_CAPABILITY_INTERNET = 12; - // Indicates that this network is available for general use. If this is - // not set applications should not attempt to communicate on this - // network. Note that this is simply informative and not enforcement - - // enforcement is handled via other means. Set by default. - NET_CAPABILITY_NOT_RESTRICTED = 13; - // Indicates that the user has indicated implicit trust of this network. - // This generally means it's a sim-selected carrier, a plugged in - // ethernet, a paired BT device or a wifi the user asked to connect to. - // Untrusted networks are probably limited to unknown wifi AP. Set by - // default. - NET_CAPABILITY_TRUSTED = 14; - // Indicates that this network is not a VPN. This capability is set by - // default and should be explicitly cleared for VPN networks. - NET_CAPABILITY_NOT_VPN = 15; - // Indicates that connectivity on this network was successfully - // validated. For example, for a network with NET_CAPABILITY_INTERNET, - // it means that Internet connectivity was successfully detected. - NET_CAPABILITY_VALIDATED = 16; - // Indicates that this network was found to have a captive portal in - // place last time it was probed. - NET_CAPABILITY_CAPTIVE_PORTAL = 17; - // Indicates that this network is not roaming. - NET_CAPABILITY_NOT_ROAMING = 18; - // Indicates that this network is available for use by apps, and not a - // network that is being kept up in the background to facilitate fast - // network switching. - NET_CAPABILITY_FOREGROUND = 19; - } - repeated NetCapability capabilities = 2; - - // Passive link bandwidth. This is a rough guide of the expected peak - // bandwidth for the first hop on the given transport. It is not measured, - // but may take into account link parameters (Radio technology, allocated - // channels, etc). - optional int32 link_up_bandwidth_kbps = 3; - optional int32 link_down_bandwidth_kbps = 4; - - optional string network_specifier = 5 [ (.android.privacy).dest = DEST_EXPLICIT ]; - - // True if this object specifies a signal strength. - optional bool can_report_signal_strength = 6; - // This is a signed integer, and higher values indicate better signal. The - // exact units are bearer-dependent. For example, Wi-Fi uses RSSI. - // Only valid if can_report_signal_strength is true. - optional sint32 signal_strength = 7; -} diff --git a/core/proto/android/net/networkrequest.proto b/core/proto/android/net/networkrequest.proto index b35a0203ff02..6794c8cd8acb 100644 --- a/core/proto/android/net/networkrequest.proto +++ b/core/proto/android/net/networkrequest.proto @@ -20,8 +20,8 @@ package android.net; option java_multiple_files = true; -import "frameworks/base/core/proto/android/net/networkcapabilities.proto"; import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/net/networkcapabilities.proto"; /** * An android.net.NetworkRequest object. diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto index 892ebf70ca75..7d68a0df23d5 100644 --- a/core/proto/android/os/batterystats.proto +++ b/core/proto/android/os/batterystats.proto @@ -19,10 +19,10 @@ option java_multiple_files = true; package android.os; -import "frameworks/base/core/proto/android/app/job/enums.proto"; import "frameworks/base/core/proto/android/os/powermanager.proto"; -import "frameworks/base/core/proto/android/telephony/enums.proto"; import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/app/job/enums.proto"; +import "frameworks/proto_logging/stats/enums/telephony/enums.proto"; message BatteryStatsProto { option (android.msg_privacy).dest = DEST_AUTOMATIC; diff --git a/core/proto/android/os/enums.proto b/core/proto/android/os/enums.proto deleted file mode 100644 index 566861b6e836..000000000000 --- a/core/proto/android/os/enums.proto +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.os; - -option java_outer_classname = "OsProtoEnums"; -option java_multiple_files = true; - -// These constants are defined in hardware/interfaces/health/1.0/types.hal -// They are primarily used by android/os/BatteryManager.java. -enum BatteryHealthEnum { - BATTERY_HEALTH_INVALID = 0; - BATTERY_HEALTH_UNKNOWN = 1; - BATTERY_HEALTH_GOOD = 2; - BATTERY_HEALTH_OVERHEAT = 3; - BATTERY_HEALTH_DEAD = 4; - BATTERY_HEALTH_OVER_VOLTAGE = 5; - BATTERY_HEALTH_UNSPECIFIED_FAILURE = 6; - BATTERY_HEALTH_COLD = 7; -} - -// Plug states, primarily used by android/os/BatteryManager.java. -enum BatteryPluggedStateEnum { - // Note that NONE is not in BatteryManager.java's constants. - BATTERY_PLUGGED_NONE = 0; - // Power source is an AC charger. - BATTERY_PLUGGED_AC = 1; - // Power source is a USB port. - BATTERY_PLUGGED_USB = 2; - // Power source is wireless. - BATTERY_PLUGGED_WIRELESS = 4; -} - -// These constants are defined in hardware/interfaces/health/1.0/types.hal -// They are primarily used by android/os/BatteryManager.java. -enum BatteryStatusEnum { - BATTERY_STATUS_INVALID = 0; - BATTERY_STATUS_UNKNOWN = 1; - BATTERY_STATUS_CHARGING = 2; - BATTERY_STATUS_DISCHARGING = 3; - BATTERY_STATUS_NOT_CHARGING = 4; - BATTERY_STATUS_FULL = 5; -} - -// These constants are defined in hardware/interfaces/thermal/1.0/types.hal -// and in hardware/interfaces/thermal/2.0/types.hal -// They are primarily used by android/os/HardwarePropertiesManager.java. -// Any change to the types in the thermal hal should be made here as well. -enum TemperatureTypeEnum { - TEMPERATURE_TYPE_UNKNOWN = -1; - TEMPERATURE_TYPE_CPU = 0; - TEMPERATURE_TYPE_GPU = 1; - TEMPERATURE_TYPE_BATTERY = 2; - TEMPERATURE_TYPE_SKIN = 3; - TEMPERATURE_TYPE_USB_PORT = 4; - TEMPERATURE_TYPE_POWER_AMPLIFIER = 5; - - // Battery Charge Limit - virtual thermal sensors. - TEMPERATURE_TYPE_BCL_VOLTAGE = 6; - TEMPERATURE_TYPE_BCL_CURRENT = 7; - TEMPERATURE_TYPE_BCL_PERCENTAGE = 8; - - // Neural Processing Unit. - TEMPERATURE_TYPE_NPU = 9; -} - -// Device throttling severity -// These constants are defined in hardware/interfaces/thermal/2.0/types.hal. -// Any change to the types in the thermal hal should be made here as well. -enum ThrottlingSeverityEnum { - // Not under throttling. - NONE = 0; - // Light throttling where UX is not impacted. - LIGHT = 1; - // Moderate throttling where UX is not largely impacted. - MODERATE = 2; - // Severe throttling where UX is largely impacted. - // Similar to 1.0 throttlingThreshold. - SEVERE = 3; - // Platform has done everything to reduce power. - CRITICAL = 4; - // Key components in platform are shutting down due to thermal condition. - // Device functionalities will be limited. - EMERGENCY = 5; - // Need shutdown immediately. - SHUTDOWN = 6; -}; - -// Device cooling device types. -// These constants are defined in hardware/interfaces/thermal/2.0/types.hal. -// Any change to the types in the thermal hal should be made here as well. -enum CoolingTypeEnum { - FAN = 0; - BATTERY = 1; - CPU = 2; - GPU = 3; - MODEM = 4; - NPU = 5; - COMPONENT = 6; -}; - -// Wakelock types, primarily used by android/os/PowerManager.java. -enum WakeLockLevelEnum { - // NOTE: Wake lock levels were previously defined as a bit field, except - // that only a few combinations were actually supported so the bit field - // was removed. This explains why the numbering scheme is so odd. If - // adding a new wake lock level, any unused value can be used. - - // Ensures that the CPU is running; the screen and keyboard backlight - // will be allowed to go off. - PARTIAL_WAKE_LOCK = 1; - - // Ensures that the screen is on (but may be dimmed); the keyboard - // backlight will be allowed to go off. If the user presses the power - // button, then the SCREEN_DIM_WAKE_LOCK will be implicitly released by - // the system, causing both the screen and the CPU to be turned off. - SCREEN_DIM_WAKE_LOCK = 6 [deprecated = true]; - - // Ensures that the screen is on at full brightness; the keyboard - // backlight will be allowed to go off. If the user presses the power - // button, then the SCREEN_BRIGHT_WAKE_LOCK will be implicitly released - // by the system, causing both the screen and the CPU to be turned off. - SCREEN_BRIGHT_WAKE_LOCK = 10 [deprecated = true]; - - // Ensures that the screen and keyboard backlight are on at full - // brightness. If the user presses the power button, then the - // FULL_WAKE_LOCK will be implicitly released by the system, causing - // both the screen and the CPU to be turned off. - FULL_WAKE_LOCK = 26 [deprecated = true]; - - // Turns the screen off when the proximity sensor activates. If the - // proximity sensor detects that an object is nearby, the screen turns - // off immediately. Shortly after the object moves away, the screen - // turns on again. - // A proximity wake lock does not prevent the device from falling asleep - // unlike FULL_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK and - // SCREEN_DIM_WAKE_LOCK. If there is no user activity and no other wake - // locks are held, then the device will fall asleep (and lock) as usual. - // However, the device will not fall asleep while the screen has been - // turned off by the proximity sensor because it effectively counts as - // ongoing user activity. - PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; - - // Put the screen in a low power state and allow the CPU to suspend if - // no other wake locks are held. This is used by the dream manager to - // implement doze mode. It currently has no effect unless the power - // manager is in the dozing state. - DOZE_WAKE_LOCK = 64; - - // Keep the device awake enough to allow drawing to occur. This is used - // by the window manager to allow applications to draw while the system - // is dozing. It currently has no effect unless the power manager is in - // the dozing state. - DRAW_WAKE_LOCK = 128; -} diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index fe65bda365af..8de30f8547a7 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -56,13 +56,13 @@ import "frameworks/base/core/proto/android/service/print.proto"; import "frameworks/base/core/proto/android/service/procstats.proto"; import "frameworks/base/core/proto/android/service/restricted_image.proto"; import "frameworks/base/core/proto/android/service/sensor_service.proto"; -import "frameworks/base/core/proto/android/service/usb.proto"; import "frameworks/base/core/proto/android/util/event_log_tags.proto"; import "frameworks/base/core/proto/android/util/log.proto"; import "frameworks/base/core/proto/android/util/textdump.proto"; import "frameworks/base/core/proto/android/privacy.proto"; import "frameworks/base/core/proto/android/section.proto"; import "frameworks/base/proto/src/ipconnectivity.proto"; +import "frameworks/proto_logging/stats/enums/service/usb.proto"; package android.os; diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto index 2d2ead455a4d..fa046c6593af 100644 --- a/core/proto/android/server/activitymanagerservice.proto +++ b/core/proto/android/server/activitymanagerservice.proto @@ -20,7 +20,6 @@ package com.android.server.am; import "frameworks/base/core/proto/android/app/activitymanager.proto"; import "frameworks/base/core/proto/android/app/appexitinfo.proto"; -import "frameworks/base/core/proto/android/app/enums.proto"; import "frameworks/base/core/proto/android/app/notification.proto"; import "frameworks/base/core/proto/android/app/profilerinfo.proto"; import "frameworks/base/core/proto/android/content/component_name.proto"; @@ -35,6 +34,7 @@ import "frameworks/base/core/proto/android/server/intentresolver.proto"; import "frameworks/base/core/proto/android/server/windowmanagerservice.proto"; import "frameworks/base/core/proto/android/util/common.proto"; import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/app/enums.proto"; option java_multiple_files = true; diff --git a/core/proto/android/server/bluetooth_manager_service.proto b/core/proto/android/server/bluetooth_manager_service.proto index 998413f05ebe..c33f66a9aeca 100644 --- a/core/proto/android/server/bluetooth_manager_service.proto +++ b/core/proto/android/server/bluetooth_manager_service.proto @@ -17,8 +17,8 @@ syntax = "proto2"; package com.android.server; -import "frameworks/base/core/proto/android/bluetooth/enums.proto"; import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/bluetooth/enums.proto"; option java_multiple_files = true; diff --git a/core/proto/android/server/connectivity/Android.bp b/core/proto/android/server/connectivity/Android.bp deleted file mode 100644 index 50c238b96307..000000000000 --- a/core/proto/android/server/connectivity/Android.bp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library_static { - name: "datastallprotosnano", - proto: { - type: "nano", - }, - srcs: [ - "data_stall_event.proto", - ], - sdk_version: "system_current", - // this is part of updatable modules(NetworkStack) which targets 29(Q) - min_sdk_version: "29", -} diff --git a/core/proto/android/server/connectivity/data_stall_event.proto b/core/proto/android/server/connectivity/data_stall_event.proto deleted file mode 100644 index 787074ba494e..000000000000 --- a/core/proto/android/server/connectivity/data_stall_event.proto +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; - -package com.android.server.connectivity; -option java_multiple_files = true; -option java_outer_classname = "DataStallEventProto"; - -enum ProbeResult { - UNKNOWN = 0; - VALID = 1; - INVALID = 2; - PORTAL = 3; - PARTIAL = 4; -} - -enum ApBand { - AP_BAND_UNKNOWN = 0; - AP_BAND_2GHZ = 1; - AP_BAND_5GHZ = 2; - AP_BAND_6GHZ = 3; -} - -// Refer to definition in TelephonyManager.java. -enum RadioTech { - RADIO_TECHNOLOGY_UNKNOWN = 0; - RADIO_TECHNOLOGY_GPRS = 1; - RADIO_TECHNOLOGY_EDGE = 2; - RADIO_TECHNOLOGY_UMTS = 3; - RADIO_TECHNOLOGY_IS95A = 4; - RADIO_TECHNOLOGY_IS95B = 5; - RADIO_TECHNOLOGY_1XRTT = 6; - RADIO_TECHNOLOGY_EVDO_0 = 7; - RADIO_TECHNOLOGY_EVDO_A = 8; - RADIO_TECHNOLOGY_HSDPA = 9; - RADIO_TECHNOLOGY_HSUPA = 10; - RADIO_TECHNOLOGY_HSPA = 11; - RADIO_TECHNOLOGY_EVDO_B = 12; - RADIO_TECHNOLOGY_LTE = 13; - RADIO_TECHNOLOGY_EHRPD = 14; - RADIO_TECHNOLOGY_HSPAP = 15; - RADIO_TECHNOLOGY_GSM = 16; - RADIO_TECHNOLOGY_TD_SCDMA = 17; - RADIO_TECHNOLOGY_IWLAN = 18; - RADIO_TECHNOLOGY_LTE_CA = 19; - RADIO_TECHNOLOGY_NR = 20; -} - -// Cellular specific information. -message CellularData { - // Indicate the radio technology at the time of data stall suspected. - optional RadioTech rat_type = 1; - // True if device is in roaming network at the time of data stall suspected. - optional bool is_roaming = 2; - // Registered network MccMnc when data stall happen - optional string network_mccmnc = 3; - // Indicate the SIM card carrier. - optional string sim_mccmnc = 4; - // Signal strength level at the time of data stall suspected. - optional int32 signal_strength = 5; -} - -// Wifi specific information. -message WifiData { - // Signal strength at the time of data stall suspected. - // RSSI range is between -55 to -110. - optional int32 signal_strength = 1; - // AP band. - optional ApBand wifi_band = 2; -} - -message DnsEvent { - // The dns return code. - repeated int32 dns_return_code = 1; - // Indicate the timestamp of the dns event. - repeated int64 dns_time = 2; -} diff --git a/core/proto/android/server/enums.proto b/core/proto/android/server/enums.proto deleted file mode 100644 index 89f7010e8d81..000000000000 --- a/core/proto/android/server/enums.proto +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.server; - -option java_outer_classname = "ServerProtoEnums"; -option java_multiple_files = true; - -enum DeviceIdleModeEnum { - // Device idle mode - not active. - DEVICE_IDLE_MODE_OFF = 0; - // Device idle mode - active in lightweight mode. - DEVICE_IDLE_MODE_LIGHT = 1; - // Device idle mode - active in full mode. - DEVICE_IDLE_MODE_DEEP = 2; -} - -enum ErrorSource { - ERROR_SOURCE_UNKNOWN = 0; - // Data app - DATA_APP = 1; - // System app - SYSTEM_APP = 2; - // System server. - SYSTEM_SERVER = 3; -} diff --git a/core/proto/android/server/job/enums.proto b/core/proto/android/server/job/enums.proto deleted file mode 100644 index 50fc0310ad99..000000000000 --- a/core/proto/android/server/job/enums.proto +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package com.android.server.job; - -// This file is for JobScheduler enums inside the server directory. If you're -// adding enums for app-side code, use the file in -// frameworks/base/core/proto/android/app/job. -option java_outer_classname = "JobServerProtoEnums"; -option java_multiple_files = true; - -// Set of constraints that a job potentially needs satisfied before it can run. -// Defined in -// frameworks/base/services/core/java/com/android/server/job/controllers/JobStatus.java -enum ConstraintEnum { - CONSTRAINT_UNKNOWN = 0; - CONSTRAINT_CHARGING = 1; - CONSTRAINT_BATTERY_NOT_LOW = 2; - CONSTRAINT_STORAGE_NOT_LOW = 3; - CONSTRAINT_TIMING_DELAY = 4; - CONSTRAINT_DEADLINE = 5; - CONSTRAINT_IDLE = 6; - CONSTRAINT_CONNECTIVITY = 7; - CONSTRAINT_CONTENT_TRIGGER = 8; - CONSTRAINT_DEVICE_NOT_DOZING = 9; - CONSTRAINT_WITHIN_QUOTA = 10; - CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 11; -} diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto index 0e2bd2605836..d18722049109 100644 --- a/core/proto/android/server/jobscheduler.proto +++ b/core/proto/android/server/jobscheduler.proto @@ -20,7 +20,6 @@ package com.android.server.job; option java_multiple_files = true; -import "frameworks/base/core/proto/android/app/job/enums.proto"; import "frameworks/base/core/proto/android/content/clipdata.proto"; import "frameworks/base/core/proto/android/content/component_name.proto"; import "frameworks/base/core/proto/android/content/intent.proto"; @@ -29,10 +28,11 @@ import "frameworks/base/core/proto/android/net/networkrequest.proto"; import "frameworks/base/core/proto/android/os/bundle.proto"; import "frameworks/base/core/proto/android/os/persistablebundle.proto"; import "frameworks/base/core/proto/android/server/appstatetracker.proto"; -import "frameworks/base/core/proto/android/server/job/enums.proto"; import "frameworks/base/core/proto/android/server/statlogger.proto"; import "frameworks/base/core/proto/android/privacy.proto"; import "frameworks/base/core/proto/android/util/quotatracker.proto"; +import "frameworks/proto_logging/stats/enums/app/job/enums.proto"; +import "frameworks/proto_logging/stats/enums/server/job/enums.proto"; message JobSchedulerServiceDumpProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; diff --git a/core/proto/android/server/location/enums.proto b/core/proto/android/server/location/enums.proto deleted file mode 100644 index 943ff181fe14..000000000000 --- a/core/proto/android/server/location/enums.proto +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.server.location; - -option java_outer_classname = "ServerLocationProtoEnums"; -option java_multiple_files = true; - -// GPS Signal Quality levels, -// primarily used by location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java -enum GpsSignalQualityEnum { - GPS_SIGNAL_QUALITY_UNKNOWN = -1; - GPS_SIGNAL_QUALITY_POOR = 0; - GPS_SIGNAL_QUALITY_GOOD = 1; -} - -// A type which distinguishes different categories of NI request, such as VOICE, UMTS_SUPL etc. -enum GnssNiType { - VOICE = 1; - UMTS_SUPL = 2; - UMTS_CTRL_PLANE = 3; - EMERGENCY_SUPL = 4; -}; - -// GNSS NI responses, used to define the response in NI structures. -enum GnssUserResponseType { - RESPONSE_ACCEPT = 1; - RESPONSE_DENY = 2; - RESPONSE_NORESP = 3; -}; - -// GNSS NI data encoding scheme. -enum GnssNiEncodingType { - ENC_NONE = 0; - ENC_SUPL_GSM_DEFAULT = 1; - ENC_SUPL_UTF8 = 2; - ENC_SUPL_UCS2 = 3; - ENC_UNKNOWN = -1; -}; - -// Protocol stack that initiated the non-framework location request. -enum NfwProtocolStack { - // Cellular control plane requests. - CTRL_PLANE = 0; - // All types of SUPL requests. - SUPL = 1; - // All types of requests from IMS. - IMS = 10; - // All types of requests from SIM. - SIM = 11; - // Requests from other protocol stacks. - OTHER_PROTOCOL_STACK = 100; -}; - -// Source initiating/receiving the location information. -enum NfwRequestor { - // Wireless service provider. - CARRIER = 0; - // Device manufacturer. - OEM = 10; - // Modem chipset vendor. - MODEM_CHIPSET_VENDOR = 11; - // GNSS chipset vendor. - GNSS_CHIPSET_VENDOR = 12; - // Other chipset vendor. - OTHER_CHIPSET_VENDOR = 13; - // Automobile client. - AUTOMOBILE_CLIENT = 20; - // Other sources. - OTHER_REQUESTOR = 100; -}; - -// Indicates whether location information was provided for this request. -enum NfwResponseType { - // Request rejected because framework has not given permission for this use case. - REJECTED = 0; - // Request accepted but could not provide location because of a failure. - ACCEPTED_NO_LOCATION_PROVIDED = 1; - // Request accepted and location provided. - ACCEPTED_LOCATION_PROVIDED = 2; -}; - -// The SUPL mode. -enum SuplMode { - // Mobile Station Based. - MSB = 0x01; - // Mobile Station Assisted. - MSA = 0x02; -}; - -// Enum that hold the bit masks for various LTE Positioning Profile settings (LPP_PROFILE -// configuration parameter). If none of the bits in the enum are set, the default setting is -// Radio Resource Location Protocol(RRLP). -enum LppProfile { - // Enable LTE Positioning Protocol user plane. - USER_PLANE = 0x01; - // Enable LTE Positioning Protocol Control plane. - CONTROL_PLANE = 0x02; -}; - -// Positioning protocol on A-Glonass system. -enum GlonassPosProtocol { - // Radio Resource Control(RRC) control-plane. - RRC_CPLANE = 0x01; - // Radio Resource Location user-plane. - RRLP_CPLANE = 0x02; - // LTE Positioning Protocol User plane. - LPP_UPLANE = 0x04; -}; - -// Configurations of how GPS functionalities should be locked when user turns off GPS On setting. -enum GpsLock { - // Lock Mobile Originated GPS functionalitues. - MO = 0x01; - // Lock Network Initiated GPS functionalities. - NI = 0x02; -}; diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto index a2f2c46cba6a..0d23946ebbb8 100644 --- a/core/proto/android/server/powermanagerservice.proto +++ b/core/proto/android/server/powermanagerservice.proto @@ -19,16 +19,16 @@ package com.android.server.power; option java_multiple_files = true; -import "frameworks/base/core/proto/android/app/enums.proto"; import "frameworks/base/core/proto/android/content/intent.proto"; -import "frameworks/base/core/proto/android/os/enums.proto"; import "frameworks/base/core/proto/android/os/looper.proto"; import "frameworks/base/core/proto/android/os/powermanager.proto"; import "frameworks/base/core/proto/android/os/worksource.proto"; import "frameworks/base/core/proto/android/providers/settings.proto"; import "frameworks/base/core/proto/android/server/wirelesschargerdetector.proto"; -import "frameworks/base/core/proto/android/view/enums.proto"; import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/app/enums.proto"; +import "frameworks/proto_logging/stats/enums/os/enums.proto"; +import "frameworks/proto_logging/stats/enums/view/enums.proto"; message PowerManagerServiceDumpProto { option (.android.msg_privacy).dest = DEST_AUTOMATIC; diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index 0453d3f3763d..c4c007d8113b 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -24,7 +24,6 @@ import "frameworks/base/core/proto/android/server/windowcontainerthumbnail.proto import "frameworks/base/core/proto/android/server/surfaceanimator.proto"; import "frameworks/base/core/proto/android/view/displaycutout.proto"; import "frameworks/base/core/proto/android/view/displayinfo.proto"; -import "frameworks/base/core/proto/android/view/enums.proto"; import "frameworks/base/core/proto/android/view/surface.proto"; import "frameworks/base/core/proto/android/view/windowlayoutparams.proto"; import "frameworks/base/core/proto/android/privacy.proto"; @@ -34,6 +33,8 @@ import "frameworks/base/core/proto/android/view/surfacecontrol.proto"; import "frameworks/base/core/proto/android/view/insetssource.proto"; import "frameworks/base/core/proto/android/view/insetssourcecontrol.proto"; +import "frameworks/proto_logging/stats/enums/view/enums.proto"; + package com.android.server.wm; option java_multiple_files = true; @@ -206,9 +207,10 @@ message DisplayContentProto { optional WindowStateProto input_method_control_target = 29; optional WindowStateProto current_focus = 30; optional ImeInsetsSourceProviderProto ime_insets_source_provider = 31; - optional bool can_show_ime = 32; + optional bool can_show_ime = 32 [deprecated=true]; optional DisplayRotationProto display_rotation = 33; + optional int32 ime_policy = 34; } /* represents DisplayArea object */ diff --git a/core/proto/android/service/battery.proto b/core/proto/android/service/battery.proto index 586411f8ad96..3a112e7c85f0 100644 --- a/core/proto/android/service/battery.proto +++ b/core/proto/android/service/battery.proto @@ -20,8 +20,8 @@ package android.service.battery; option java_multiple_files = true; option java_outer_classname = "BatteryServiceProto"; -import "frameworks/base/core/proto/android/os/enums.proto"; import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/os/enums.proto"; message BatteryServiceDumpProto { option (android.msg_privacy).dest = DEST_AUTOMATIC; diff --git a/core/proto/android/service/procstats.proto b/core/proto/android/service/procstats.proto index 7a4c0706e119..57051f07d124 100644 --- a/core/proto/android/service/procstats.proto +++ b/core/proto/android/service/procstats.proto @@ -21,8 +21,8 @@ option java_multiple_files = true; option java_outer_classname = "ProcessStatsServiceProto"; import "frameworks/base/core/proto/android/util/common.proto"; -import "frameworks/base/core/proto/android/service/procstats_enum.proto"; import "frameworks/base/core/proto/android/privacy.proto"; +import "frameworks/proto_logging/stats/enums/service/procstats_enum.proto"; /** * Data from ProcStatsService Dumpsys diff --git a/core/proto/android/service/procstats_enum.proto b/core/proto/android/service/procstats_enum.proto deleted file mode 100644 index 2abf3730aa9f..000000000000 --- a/core/proto/android/service/procstats_enum.proto +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.service.procstats; - -option java_multiple_files = true; -option java_outer_classname = "ProcessStatsEnums"; - -enum ScreenState { - SCREEN_STATE_UNKNOWN = 0; - SCREEN_STATE_OFF = 1; - SCREEN_STATE_ON = 2; -} - -enum MemoryState { - MEMORY_STATE_UNKNOWN = 0; - MEMORY_STATE_NORMAL = 1; // normal. - MEMORY_STATE_MODERATE = 2; // moderate memory pressure. - MEMORY_STATE_LOW = 3; // low memory. - MEMORY_STATE_CRITICAL = 4; // critical memory. -} - -// this enum list is from frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java -// and not frameworks/base/core/java/android/app/ActivityManager.java -enum ProcessState { - PROCESS_STATE_UNKNOWN = 0; - // Persistent system process. - PROCESS_STATE_PERSISTENT = 1; - // Top activity; actually any visible activity. - PROCESS_STATE_TOP = 2; - // Important foreground process (ime, wallpaper, etc). - PROCESS_STATE_IMPORTANT_FOREGROUND = 3; - // Important background process. - PROCESS_STATE_IMPORTANT_BACKGROUND = 4; - // Performing backup operation. - PROCESS_STATE_BACKUP = 5; - // Background process running a service. - PROCESS_STATE_SERVICE = 6; - // Process not running, but would be if there was enough RAM. - PROCESS_STATE_SERVICE_RESTARTING = 7; - // Process running a receiver. - PROCESS_STATE_RECEIVER = 8; - // Heavy-weight process (currently not used). - PROCESS_STATE_HEAVY_WEIGHT = 9; - // Process hosting home/launcher app when not on top. - PROCESS_STATE_HOME = 10; - // Process hosting the last app the user was in. - PROCESS_STATE_LAST_ACTIVITY = 11; - // Cached process hosting a previous activity. - PROCESS_STATE_CACHED_ACTIVITY = 12; - // Cached process hosting a client activity. - PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 13; - // Cached process that is empty. - PROCESS_STATE_CACHED_EMPTY = 14; -} - -enum ServiceOperationState { - SERVICE_OPERATION_STATE_UNKNOWN = 0; - SERVICE_OPERATION_STATE_RUNNING = 1; - SERVICE_OPERATION_STATE_STARTED = 2; - SERVICE_OPERATION_STATE_FOREGROUND = 3; - SERVICE_OPERATION_STATE_BOUND = 4; - SERVICE_OPERATION_STATE_EXECUTING = 5; -} - -// this enum list is from frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java -// and not frameworks/base/core/java/android/app/ActivityManager.java -enum AggregatedProcessState { - AGGREGATED_PROCESS_STATE_UNKNOWN = 0; - // Persistent system process; PERSISTENT or PERSISTENT_UI in ActivityManager - AGGREGATED_PROCESS_STATE_PERSISTENT = 1; - // Top activity; actually any visible activity; TOP or TOP_SLEEPING in ActivityManager - AGGREGATED_PROCESS_STATE_TOP = 2; - // Bound top foreground process; BOUND_TOP or BOUND_FOREGROUND_SERVICE in ActivityManager - AGGREGATED_PROCESS_STATE_BOUND_TOP_OR_FGS = 3; - // Important foreground process; FOREGROUND_SERVICE in ActivityManager - AGGREGATED_PROCESS_STATE_FGS = 4; - // Important foreground process ; IMPORTANT_FOREGROUND in ActivityManager - AGGREGATED_PROCESS_STATE_IMPORTANT_FOREGROUND = 5; - // Various background processes; IMPORTANT_BACKGROUND, TRANSIENT_BACKGROUND, BACKUP, SERVICE, - // HEAVY_WEIGHT in ActivityManager - AGGREGATED_PROCESS_STATE_BACKGROUND = 6; - // Process running a receiver; RECEIVER in ActivityManager - AGGREGATED_PROCESS_STATE_RECEIVER = 7; - // Various cached processes; HOME, LAST_ACTIVITY, CACHED_ACTIVITY, CACHED_RECENT, - // CACHED_ACTIVITY_CLIENT, CACHED_EMPTY in ActivityManager - AGGREGATED_PROCESS_STATE_CACHED = 8; -}
\ No newline at end of file diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto deleted file mode 100644 index 40c5a85e1f24..000000000000 --- a/core/proto/android/service/usb.proto +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.service.usb; - -option java_multiple_files = true; -option java_outer_classname = "UsbServiceProto"; - -import "frameworks/base/core/proto/android/content/component_name.proto"; -import "frameworks/base/core/proto/android/service/enums.proto"; -import "frameworks/base/core/proto/android/privacy.proto"; - -message UsbServiceDumpProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional UsbDeviceManagerProto device_manager = 1; - optional UsbHostManagerProto host_manager = 2; - optional UsbPortManagerProto port_manager = 3; - optional UsbAlsaManagerProto alsa_manager = 4; - optional UsbSettingsManagerProto settings_manager = 5; - optional UsbPermissionsManagerProto permissions_manager = 6; -} - -message UsbDeviceManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional UsbHandlerProto handler = 1; - optional UsbDebuggingManagerProto debugging_manager = 2; -} - -message UsbHandlerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - /* Same as android.hardware.usb.gadget.V1_0.GadgetFunction.* */ - enum Function { - FUNCTION_ADB = 1; - FUNCTION_ACCESSORY = 2; - FUNCTION_MTP = 4; - FUNCTION_MIDI = 8; - FUNCTION_PTP = 16; - FUNCTION_RNDIS = 32; - FUNCTION_AUDIO_SOURCE = 64; - } - - repeated Function current_functions = 1; - optional bool current_functions_applied = 2; - repeated Function screen_unlocked_functions = 3; - optional bool screen_locked = 4; - optional bool connected = 5; - optional bool configured = 6; - optional UsbAccessoryProto current_accessory = 7; - optional bool host_connected = 8; - optional bool source_power = 9; - optional bool sink_power = 10; - optional bool usb_charging = 11; - optional bool hide_usb_notification = 12; - optional bool audio_accessory_connected = 13; - optional bool adb_enabled = 14; - optional string kernel_state = 15; - optional string kernel_function_list = 16; -} - -message UsbAccessoryProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional string manufacturer = 1; - optional string model = 2; - // For "classical" USB-accessories the manufacturer bakes this into the - // firmware of the device. If an Android phone is configured as accessory, the - // app that sets up the accessory side of the connection set this. Either way, - // these are part of the detection protocol, and so they cannot be user set or - // unique. - optional string description = 3; - optional string version = 4; - optional string uri = 5 [ (android.privacy).dest = DEST_EXPLICIT ]; - // Non-resettable hardware ID. - optional string serial = 6 [ (android.privacy).dest = DEST_LOCAL ]; -} - -message UsbDebuggingManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional bool connected_to_adb = 1; - // A workstation that connects to the phone for debugging is identified by - // this key. - optional string last_key_received = 2 [ (android.privacy).dest = DEST_EXPLICIT ]; - optional string user_keys = 3 [ (android.privacy).dest = DEST_LOCAL ]; - optional string system_keys = 4 [ (android.privacy).dest = DEST_LOCAL ]; -} - -message UsbHostManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional android.content.ComponentNameProto default_usb_host_connection_handler = 1; - repeated UsbDeviceProto devices = 2; - optional int32 num_connects = 3; - repeated UsbConnectionRecordProto connections = 4; -} - -message UsbDeviceProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - // Generic USB name, not user-provided. - optional string name = 1; - // ID specific to the vendor, not the device. - optional int32 vendor_id = 2; - // ID of this product type: Each vendor gives each product a unique ID. E.g. - // all mice of the same model would have the same ID. - optional int32 product_id = 3; - optional int32 class = 4; - optional int32 subclass = 5; - optional int32 protocol = 6; - optional string manufacturer_name = 7; - optional string product_name = 8; - optional string version = 9; - // Non-resettable hardware ID. - optional string serial_number = 10 [ (android.privacy).dest = DEST_LOCAL ]; - repeated UsbConfigurationProto configurations = 11; -} - -message UsbConfigurationProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - // A single USB device can have several configurations and the app accessing - // the USB device can switch between them. At any time only one can be active. - // Each configuration can present completely different interfaces end - // endpoints, i.e. a completely different behavior. - optional int32 id = 1; - // Hardware-defined name, not set by the user. - optional string name = 2; - optional uint32 attributes = 3; - optional int32 max_power = 4; - repeated UsbInterfaceProto interfaces = 5; -} - -message UsbInterfaceProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - // Hardware defined. This is the id used by the app to identify the interface. - optional int32 id = 1; - optional int32 alternate_settings = 2; - optional string name = 3; - optional int32 class = 4; - optional int32 subclass = 5; - optional int32 protocol = 6; - repeated UsbEndPointProto endpoints = 7; -} - -message UsbEndPointProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional int32 endpoint_number = 1; - optional android.service.UsbEndPointDirection direction = 2; - // The address of the endpoint. Needed to read and write to the endpoint. - optional int32 address = 3; - optional android.service.UsbEndPointType type = 4; - optional uint32 attributes = 5; - optional int32 max_packet_size = 6; - optional int32 interval = 7; -} - -message UsbConnectionRecordProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - // usb device's address, e.g. 001/002, nothing about the phone - optional string device_address = 1; - optional android.service.UsbConnectionRecordMode mode = 2; - optional int64 timestamp = 3; - optional int32 manufacturer = 4; - optional int32 product = 5; - optional UsbIsHeadsetProto is_headset = 6; -} - -message UsbIsHeadsetProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional bool in = 1; - optional bool out = 2; -} - -message UsbPortManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional bool is_simulation_active = 1; - repeated UsbPortInfoProto usb_ports = 2; -} - -message UsbPortInfoProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional UsbPortProto port = 1; - optional UsbPortStatusProto status = 2; - optional bool can_change_mode = 3; - optional bool can_change_power_role = 4; - optional bool can_change_data_role = 5; - optional int64 connected_at_millis = 6; - optional int64 last_connect_duration_millis = 7; -} - -message UsbPortProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - /* Same as android.hardware.usb.V1_1.Constants.PortMode_1_1 */ - enum Mode { - MODE_NONE = 0; - MODE_UFP = 1; - MODE_DFP = 2; - MODE_DRP = 3; - MODE_AUDIO_ACCESSORY = 4; - MODE_DEBUG_ACCESSORY = 8; - } - - // ID of the port. A device (eg: Chromebooks) might have multiple ports. - optional string id = 1; - repeated Mode supported_modes = 2; -} - -/* Same as android.hardware.usb.V1_2.Constants.ContaminantPresenceStatus */ -enum ContaminantPresenceStatus { - CONTAMINANT_STATUS_UNKNOWN = 0; - CONTAMINANT_STATUS_NOT_SUPPORTED = 1; - CONTAMINANT_STATUS_DISABLED = 2; - CONTAMINANT_STATUS_NOT_DETECTED = 3; - CONTAMINANT_STATUS_DETECTED = 4; -} - -message UsbPortStatusProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - /* Same as android.hardware.usb.V1_0.Constants.PortPowerRole */ - enum PowerRole { - POWER_ROLE_NONE = 0; - POWER_ROLE_SOURCE = 1; - POWER_ROLE_SINK = 2; - } - - /* Same as android.hardware.usb.V1_0.Constants.PortDataRole */ - enum DataRole { - DATA_ROLE_NONE = 0; - DATA_ROLE_HOST = 1; - DATA_ROLE_DEVICE = 2; - } - - optional bool connected = 1; - optional UsbPortProto.Mode current_mode = 2; - optional PowerRole power_role = 3; - optional DataRole data_role = 4; - repeated UsbPortStatusRoleCombinationProto role_combinations = 5; - optional ContaminantPresenceStatus contaminant_presence_status = 6; -} - -message UsbPortStatusRoleCombinationProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional UsbPortStatusProto.PowerRole power_role = 1; - optional UsbPortStatusProto.DataRole data_role = 2; -} - -message UsbAlsaManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional int32 cards_parser = 1; - repeated UsbAlsaDeviceProto alsa_devices = 2; - repeated UsbMidiDeviceProto midi_devices = 3; -} - -message UsbAlsaDeviceProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional int32 card = 1; - optional int32 device = 2; - optional string name = 3; - optional bool has_playback = 4; - optional bool has_capture = 5; - // usb device's address, e.g. 001/002, nothing about the phone - optional string address = 6; -} - -message UsbMidiDeviceProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional int32 card = 1; - optional int32 device = 2; - // usb device's address, e.g. 001/002, nothing about the phone - optional string device_address = 3; -} - -message UsbSettingsManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - repeated UsbUserSettingsManagerProto user_settings = 1; - repeated UsbProfileGroupSettingsManagerProto profile_group_settings = 2; -} - -message UsbUserSettingsManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional int32 user_id = 1; - reserved 2; // previously device_permissions, now unused - reserved 3; // previously accessory_permissions, now unused - repeated UsbDeviceAttachedActivities device_attached_activities = 4; - repeated UsbAccessoryAttachedActivities accessory_attached_activities = 5; -} - -message UsbProfileGroupSettingsManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - // The user id of the personal profile if the device has a work profile. - optional int32 parent_user_id = 1; - repeated UsbSettingsDevicePreferenceProto device_preferences = 2; - repeated UsbSettingsAccessoryPreferenceProto accessory_preferences = 3; -} - -message UsbSettingsDevicePreferenceProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional UsbDeviceFilterProto filter = 1; - optional UserPackageProto user_package = 2; -} - -message UsbPermissionsManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - repeated UsbUserPermissionsManagerProto user_permissions = 1; -} - -message UsbUserPermissionsManagerProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional int32 user_id = 1; - - repeated UsbDevicePermissionProto device_permissions = 2; - repeated UsbAccessoryPermissionProto accessory_permissions = 3; - - repeated UsbDevicePersistentPermissionProto device_persistent_permissions = 4; - repeated UsbAccessoryPersistentPermissionProto accessory_persistent_permissions = 5; -} - -message UsbDevicePermissionProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - // Name of device set by manufacturer - // All devices of the same model have the same name - optional string device_name = 1; - repeated int32 uids = 2; -} - -message UsbAccessoryPermissionProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - // Description of accessory set by manufacturer - // All accessories of the same model have the same description - optional string accessory_description = 1; - repeated int32 uids = 2; -} - -message UsbDevicePersistentPermissionProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional UsbDeviceFilterProto device_filter = 1; - repeated UsbUidPermissionProto permission_values = 2; -} - -message UsbAccessoryPersistentPermissionProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional UsbAccessoryFilterProto accessory_filter = 1; - repeated UsbUidPermissionProto permission_values = 2; -} - -message UsbUidPermissionProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional int32 uid = 1; - optional bool is_granted = 2; -} - -message UsbDeviceFilterProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - // Mirrors the vendor_id of UsbDeviceProto. - optional int32 vendor_id = 1; - optional int32 product_id = 2; - optional int32 class = 3; - optional int32 subclass = 4; - optional int32 protocol = 5; - optional string manufacturer_name = 6; - optional string product_name = 7; - optional string serial_number = 8 [ (android.privacy).dest = DEST_EXPLICIT ]; -} - -message UserPackageProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional int32 user_id = 1; - optional string package_name =2; -} - -message UsbSettingsAccessoryPreferenceProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional UsbAccessoryFilterProto filter = 1; - optional UserPackageProto user_package = 2; -} - -message UsbAccessoryFilterProto { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional string manufacturer = 1; - optional string model = 2; - optional string version = 3; -} - -message UsbDeviceAttachedActivities { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional android.content.ComponentNameProto activity = 1; - repeated UsbDeviceFilterProto filters = 2; -} - -message UsbAccessoryAttachedActivities { - option (android.msg_privacy).dest = DEST_AUTOMATIC; - - optional android.content.ComponentNameProto activity = 1; - repeated UsbAccessoryFilterProto filters = 2; -} diff --git a/core/proto/android/stats/camera/Android.bp b/core/proto/android/stats/camera/Android.bp deleted file mode 100644 index cc75e57af87b..000000000000 --- a/core/proto/android/stats/camera/Android.bp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2020 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library { - name: "cameraprotosnano", - proto: { - type: "nano", - }, - srcs: [ - "*.proto", - ], - java_version: "1.8", - target: { - android: { - jarjar_rules: "jarjar-rules.txt", - }, - host: { - static_libs: ["libprotobuf-java-nano"], - } - }, - sdk_version: "core_platform", -} diff --git a/core/proto/android/stats/camera/camera.proto b/core/proto/android/stats/camera/camera.proto deleted file mode 100644 index 406285551d98..000000000000 --- a/core/proto/android/stats/camera/camera.proto +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.stats.camera; -option java_multiple_files = true; - -message CameraStreamProto { - // The stream width (in pixels) - optional int32 width = 1; - // The stream height (in pixels) - optional int32 height = 2; - // The format of the stream - optional int32 format = 3; - // The dataspace of the stream - optional int32 data_space = 4; - // The usage flag of the stream - optional int64 usage = 5; - - // The number of requests for this stream - optional int64 request_count = 6; - // The number of buffer error for this stream - optional int64 error_count = 7; - // The capture latency of first request for this stream - optional int32 first_capture_latency_millis = 8; - - // The maximum number of hal buffers - optional int32 max_hal_buffers = 9; - // The maximum number of app buffers - optional int32 max_app_buffers = 10; -} diff --git a/core/proto/android/stats/camera/jarjar-rules.txt b/core/proto/android/stats/camera/jarjar-rules.txt deleted file mode 100644 index 40043a861ceb..000000000000 --- a/core/proto/android/stats/camera/jarjar-rules.txt +++ /dev/null @@ -1 +0,0 @@ -rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1 diff --git a/core/proto/android/stats/connectivity/Android.bp b/core/proto/android/stats/connectivity/Android.bp deleted file mode 100644 index 5e6ac3cd3ca1..000000000000 --- a/core/proto/android/stats/connectivity/Android.bp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library_static { - name: "networkstackprotos", - proto: { - type: "lite", - }, - srcs: [ - "network_stack.proto", - ], - sdk_version: "system_29", -} - -java_library_static { - name: "tetheringprotos", - proto: { - type: "lite", - }, - srcs: [ - "tethering.proto", - ], - apex_available: [ - "com.android.tethering", - ], - sdk_version: "system_current", -} diff --git a/core/proto/android/stats/connectivity/network_stack.proto b/core/proto/android/stats/connectivity/network_stack.proto deleted file mode 100644 index e9726d7ce195..000000000000 --- a/core/proto/android/stats/connectivity/network_stack.proto +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; - -package android.stats.connectivity; -option java_multiple_files = true; -option java_outer_classname = "NetworkStackProto"; - -enum DhcpRenewResult { - RR_UNKNOWN = 0; - RR_SUCCESS = 1; - RR_ERROR_NAK = 2; - RR_ERROR_IP_MISMATCH = 3; - RR_ERROR_IP_EXPIRE = 4; -} - -enum DisconnectCode { - DC_NONE = 0; - DC_NORMAL_TERMINATION = 1; - DC_PROVISIONING_FAIL = 2; - DC_ERROR_STARTING_IPV4 = 4; - DC_ERROR_STARTING_IPV6 = 5; - DC_ERROR_STARTING_IPREACHABILITYMONITOR = 6; - DC_INVALID_PROVISIONING = 7; - DC_INTERFACE_NOT_FOUND = 8; - DC_PROVISIONING_TIMEOUT = 9; -} - -enum TransportType { - TT_UNKNOWN = 0; - // Indicates this network uses a Cellular transport - TT_CELLULAR = 1; - // Indicates this network uses a Wi-Fi transport - TT_WIFI = 2; - // Indicates this network uses a Bluetooth transport - TT_BLUETOOTH = 3; - // Indicates this network uses an Ethernet transport - TT_ETHERNET = 4; - // Indicates this network uses a Wi-Fi Aware transport - TT_WIFI_AWARE = 5; - // Indicates this network uses a LoWPAN transport - TT_LOWPAN = 6; - // Indicates this network uses a Cellular+VPN transport - TT_CELLULAR_VPN = 7; - // Indicates this network uses a Wi-Fi+VPN transport - TT_WIFI_VPN = 8; - // Indicates this network uses a Bluetooth+VPN transport - TT_BLUETOOTH_VPN = 9; - // Indicates this network uses an Ethernet+VPN transport - TT_ETHERNET_VPN = 10; - // Indicates this network uses a Wi-Fi+Cellular+VPN transport - TT_WIFI_CELLULAR_VPN = 11; - // Indicates this network uses for test only - TT_TEST = 12; -} - -enum DhcpFeature { - DF_UNKNOWN = 0; - // DHCP INIT-REBOOT state - DF_INITREBOOT = 1; - // DHCP rapid commit option - DF_RAPIDCOMMIT = 2; - // Duplicate address detection - DF_DAD = 3; - // Fast initial Link setup - DF_FILS = 4; -} - -enum HostnameTransResult { - HTR_UNKNOWN = 0; - HTR_SUCCESS = 1; - HTR_FAILURE = 2; - HTR_DISABLE = 3; -} - -enum ProbeResult { - PR_UNKNOWN = 0; - PR_SUCCESS = 1; - PR_FAILURE = 2; - PR_PORTAL = 3; - // DNS query for the probe host returned a private IP address - PR_PRIVATE_IP_DNS = 4; -} - -enum ValidationResult { - VR_UNKNOWN = 0; - VR_SUCCESS = 1; - VR_FAILURE = 2; - VR_PORTAL = 3; - VR_PARTIAL = 4; -} - -enum ProbeType { - PT_UNKNOWN = 0; - PT_DNS = 1; - PT_HTTP = 2; - PT_HTTPS = 3; - PT_PAC = 4; - PT_FALLBACK = 5; - PT_PRIVDNS = 6; - PT_CAPPORT_API = 7; -} - -// The Dhcp error code is defined in android.net.metrics.DhcpErrorEvent -enum DhcpErrorCode { - ET_UNKNOWN = 0; - ET_L2_ERROR = 1; - ET_L3_ERROR = 2; - ET_L4_ERROR = 3; - ET_DHCP_ERROR = 4; - ET_MISC_ERROR = 5; - /* Reserve for error type - // ET_L2_ERROR_TYPE = ET_L2_ERROR << 8; - ET_L2_ERROR_TYPE = 256; - // ET_L3_ERROR_TYPE = ET_L3_ERROR << 8; - ET_L3_ERROR_TYPE = 512; - // ET_L4_ERROR_TYPE = ET_L4_ERROR << 8; - ET_L4_ERROR_TYPE = 768; - // ET_DHCP_ERROR_TYPE = ET_DHCP_ERROR << 8; - ET_DHCP_ERROR_TYPE = 1024; - // ET_MISC_ERROR_TYPE = ET_MISC_ERROR << 8; - ET_MISC_ERROR_TYPE = 1280; - */ - // ET_L2_TOO_SHORT = (ET_L2_ERROR_TYPE | 0x1) << 16; - ET_L2_TOO_SHORT = 16842752; - // ET_L2_WRONG_ETH_TYPE = (ET_L2_ERROR_TYPE | 0x2) << 16; - ET_L2_WRONG_ETH_TYPE = 16908288; - // ET_L3_TOO_SHORT = (ET_L3_ERROR_TYPE | 0x1) << 16; - ET_L3_TOO_SHORT = 33619968; - // ET_L3_NOT_IPV4 = (ET_L3_ERROR_TYPE | 0x2) << 16; - ET_L3_NOT_IPV4 = 33685504; - // ET_L3_INVALID_IP = (ET_L3_ERROR_TYPE | 0x3) << 16; - ET_L3_INVALID_IP = 33751040; - // ET_L4_NOT_UDP = (ET_L4_ERROR_TYPE | 0x1) << 16; - ET_L4_NOT_UDP = 50397184; - // ET_L4_WRONG_PORT = (ET_L4_ERROR_TYPE | 0x2) << 16; - ET_L4_WRONG_PORT = 50462720; - // ET_BOOTP_TOO_SHORT = (ET_DHCP_ERROR_TYPE | 0x1) << 16; - ET_BOOTP_TOO_SHORT = 67174400; - // ET_DHCP_BAD_MAGIC_COOKIE = (ET_DHCP_ERROR_TYPE | 0x2) << 16; - ET_DHCP_BAD_MAGIC_COOKIE = 67239936; - // ET_DHCP_INVALID_OPTION_LENGTH = (ET_DHCP_ERROR_TYPE | 0x3) << 16; - ET_DHCP_INVALID_OPTION_LENGTH = 67305472; - // ET_DHCP_NO_MSG_TYPE = (ET_DHCP_ERROR_TYPE | 0x4) << 16; - ET_DHCP_NO_MSG_TYPE = 67371008; - // ET_DHCP_UNKNOWN_MSG_TYPE = (ET_DHCP_ERROR_TYPE | 0x5) << 16; - ET_DHCP_UNKNOWN_MSG_TYPE = 67436544; - // ET_DHCP_NO_COOKIE = (ET_DHCP_ERROR_TYPE | 0x6) << 16; - ET_DHCP_NO_COOKIE = 67502080; - // ET_BUFFER_UNDERFLOW = (ET_MISC_ERROR_TYPE | 0x1) << 16; - ET_BUFFER_UNDERFLOW = 83951616; - // ET_RECEIVE_ERROR = (ET_MISC_ERROR_TYPE | 0x2) << 16; - ET_RECEIVE_ERROR = 84017152; - // ET_PARSING_ERROR = (ET_MISC_ERROR_TYPE | 0x3) << 16; - ET_PARSING_ERROR = 84082688; -} - -enum NetworkQuirkEvent { - QE_UNKNOWN = 0; - QE_IPV6_PROVISIONING_ROUTER_LOST = 1; -} - -message NetworkStackEventData { - -} - diff --git a/core/proto/android/stats/connectivity/tethering.proto b/core/proto/android/stats/connectivity/tethering.proto deleted file mode 100644 index 13f0b8c44fb5..000000000000 --- a/core/proto/android/stats/connectivity/tethering.proto +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -syntax = "proto2"; -package android.stats.connectivity; -option java_multiple_files = true; -option java_outer_classname = "TetheringProto"; - -enum ErrorCode { - EC_NO_ERROR = 0; - EC_UNKNOWN_IFACE = 1; - EC_SERVICE_UNAVAIL = 2; - EC_UNSUPPORTED = 3; - EC_UNAVAIL_IFACE = 4; - EC_INTERNAL_ERROR = 5; - EC_TETHER_IFACE_ERROR = 6; - EC_UNTETHER_IFACE_ERROR = 7; - EC_ENABLE_FORWARDING_ERROR = 8; - EC_DISABLE_FORWARDING_ERROR = 9; - EC_IFACE_CFG_ERROR = 10; - EC_PROVISIONING_FAILED = 11; - EC_DHCPSERVER_ERROR = 12; - EC_ENTITLEMENT_UNKNOWN = 13; - EC_NO_CHANGE_TETHERING_PERMISSION = 14; - EC_NO_ACCESS_TETHERING_PERMISSION = 15; - EC_UNKNOWN_TYPE = 16; -} - -enum DownstreamType { - // Unspecific tethering type. - DS_UNSPECIFIED = 0; - // Wifi tethering type. - DS_TETHERING_WIFI = 1; - // USB tethering type. - DS_TETHERING_USB = 2; - // Bluetooth tethering type. - DS_TETHERING_BLUETOOTH = 3; - // Wifi P2p tethering type. - DS_TETHERING_WIFI_P2P = 4; - // NCM (Network Control Model) local tethering type. - DS_TETHERING_NCM = 5; - // Ethernet tethering type. - DS_TETHERING_ETHERNET = 6; -} - -enum UpstreamType { - UT_UNKNOWN = 0; - // Indicates upstream using a Cellular transport. - UT_CELLULAR = 1; - // Indicates upstream using a Wi-Fi transport. - UT_WIFI = 2; - // Indicates upstream using a Bluetooth transport. - UT_BLUETOOTH = 3; - // Indicates upstream using an Ethernet transport. - UT_ETHERNET = 4; - // Indicates upstream using a Wi-Fi Aware transport. - UT_WIFI_AWARE = 5; - // Indicates upstream using a LoWPAN transport. - UT_LOWPAN = 6; - // Indicates upstream using a Cellular+VPN transport. - UT_CELLULAR_VPN = 7; - // Indicates upstream using a Wi-Fi+VPN transport. - UT_WIFI_VPN = 8; - // Indicates upstream using a Bluetooth+VPN transport. - UT_BLUETOOTH_VPN = 9; - // Indicates upstream using an Ethernet+VPN transport. - UT_ETHERNET_VPN = 10; - // Indicates upstream using a Wi-Fi+Cellular+VPN transport. - UT_WIFI_CELLULAR_VPN = 11; - // Indicates upstream using for test only. - UT_TEST = 12; - // Indicates upstream using DUN capability + Cellular transport. - UT_DUN_CELLULAR = 13; -} - -enum UserType { - // Unknown. - USER_UNKNOWN = 0; - // Settings. - USER_SETTINGS = 1; - // System UI. - USER_SYSTEMUI = 2; - // Google mobile service. - USER_GMS = 3; -} diff --git a/core/proto/android/stats/devicepolicy/Android.bp b/core/proto/android/stats/devicepolicy/Android.bp deleted file mode 100644 index 5fb278a34dae..000000000000 --- a/core/proto/android/stats/devicepolicy/Android.bp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library_static { - name: "devicepolicyprotosnano", - proto: { - type: "nano", - }, - srcs: [ - "*.proto", - ], - java_version: "1.8", - target: { - android: { - jarjar_rules: "jarjar-rules.txt", - }, - host: { - static_libs: ["libprotobuf-java-nano"], - } - }, - sdk_version: "core_platform", -} diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto deleted file mode 100644 index 7c1a04944d68..000000000000 --- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.stats.devicepolicy; -option java_multiple_files = true; - -/** - * Id for device policy features. - */ -enum EventId { - SET_PASSWORD_QUALITY = 1; - SET_PASSWORD_MINIMUM_LENGTH = 2; - SET_PASSWORD_MINIMUM_NUMERIC = 3; - SET_PASSWORD_MINIMUM_NON_LETTER = 4; - SET_PASSWORD_MINIMUM_LETTERS = 5; - SET_PASSWORD_MINIMUM_LOWER_CASE = 6; - SET_PASSWORD_MINIMUM_UPPER_CASE = 7; - SET_PASSWORD_MINIMUM_SYMBOLS = 8; - SET_KEYGUARD_DISABLED_FEATURES = 9; - LOCK_NOW = 10; - WIPE_DATA_WITH_REASON = 11; - ADD_USER_RESTRICTION = 12; - REMOVE_USER_RESTRICTION = 13; - SET_SECURE_SETTING = 14; - SET_SECURITY_LOGGING_ENABLED = 15; - RETRIEVE_SECURITY_LOGS = 16; - RETRIEVE_PRE_REBOOT_SECURITY_LOGS = 17; - SET_PERMISSION_POLICY = 18; - SET_PERMISSION_GRANT_STATE = 19; - INSTALL_KEY_PAIR = 20; - INSTALL_CA_CERT = 21; - CHOOSE_PRIVATE_KEY_ALIAS = 22; - REMOVE_KEY_PAIR = 23; - UNINSTALL_CA_CERTS = 24; - SET_CERT_INSTALLER_PACKAGE = 25; - SET_ALWAYS_ON_VPN_PACKAGE = 26; - SET_PERMITTED_INPUT_METHODS = 27; - SET_PERMITTED_ACCESSIBILITY_SERVICES = 28; - SET_SCREEN_CAPTURE_DISABLED = 29; - SET_CAMERA_DISABLED = 30; - QUERY_SUMMARY_FOR_USER = 31; - QUERY_SUMMARY = 32; - QUERY_DETAILS = 33; - REBOOT = 34; - SET_MASTER_VOLUME_MUTED = 35; - SET_AUTO_TIME_REQUIRED = 36; - SET_KEYGUARD_DISABLED = 37; - SET_STATUS_BAR_DISABLED = 38; - SET_ORGANIZATION_COLOR = 39; - SET_PROFILE_NAME = 40; - SET_USER_ICON = 41; - SET_DEVICE_OWNER_LOCK_SCREEN_INFO = 42; - SET_SHORT_SUPPORT_MESSAGE = 43; - SET_LONG_SUPPORT_MESSAGE = 44; - SET_CROSS_PROFILE_CONTACTS_SEARCH_DISABLED = 45; - SET_CROSS_PROFILE_CALLER_ID_DISABLED = 46; - SET_BLUETOOTH_CONTACT_SHARING_DISABLED = 47; - ADD_CROSS_PROFILE_INTENT_FILTER = 48; - ADD_CROSS_PROFILE_WIDGET_PROVIDER = 49; - SET_SYSTEM_UPDATE_POLICY = 50; - SET_LOCKTASK_MODE_ENABLED = 51; - ADD_PERSISTENT_PREFERRED_ACTIVITY = 52; - REQUEST_BUGREPORT = 53; - GET_WIFI_MAC_ADDRESS = 54; - REQUEST_QUIET_MODE_ENABLED = 55; - WORK_PROFILE_LOCATION_CHANGED = 56; - DO_USER_INFO_CLICKED = 57; - TRANSFER_OWNERSHIP = 58; - GENERATE_KEY_PAIR = 59; - SET_KEY_PAIR_CERTIFICATE = 60; - SET_KEEP_UNINSTALLED_PACKAGES = 61; - SET_APPLICATION_RESTRICTIONS = 62; - SET_APPLICATION_HIDDEN = 63; - ENABLE_SYSTEM_APP = 64; - ENABLE_SYSTEM_APP_WITH_INTENT = 65; - INSTALL_EXISTING_PACKAGE = 66; - SET_UNINSTALL_BLOCKED = 67; - SET_PACKAGES_SUSPENDED = 68; - ON_LOCK_TASK_MODE_ENTERING = 69; - SET_CROSS_PROFILE_CALENDAR_PACKAGES = 70; - GET_USER_PASSWORD_COMPLEXITY_LEVEL = 72; - INSTALL_SYSTEM_UPDATE = 73; - INSTALL_SYSTEM_UPDATE_ERROR = 74; - IS_MANAGED_KIOSK = 75; - IS_UNATTENDED_MANAGED_KIOSK = 76; - PROVISIONING_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE = 77; - PROVISIONING_PERSISTENT_DEVICE_OWNER = 78; - - // existing Tron logs to be migrated to statsd - PROVISIONING_ENTRY_POINT_NFC = 79; - PROVISIONING_ENTRY_POINT_QR_CODE = 80; - PROVISIONING_ENTRY_POINT_CLOUD_ENROLLMENT = 81; - PROVISIONING_ENTRY_POINT_ADB = 82; - PROVISIONING_ENTRY_POINT_TRUSTED_SOURCE = 83; - PROVISIONING_DPC_PACKAGE_NAME = 84; - PROVISIONING_DPC_INSTALLED_BY_PACKAGE = 85; - PROVISIONING_PROVISIONING_ACTIVITY_TIME_MS = 86; - PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS = 87; - PROVISIONING_ENCRYPT_DEVICE_ACTIVITY_TIME_MS = 88; - PROVISIONING_WEB_ACTIVITY_TIME_MS = 89; - PROVISIONING_TRAMPOLINE_ACTIVITY_TIME_MS = 90 [deprecated=true]; - PROVISIONING_POST_ENCRYPTION_ACTIVITY_TIME_MS = 91 [deprecated=true]; - PROVISIONING_FINALIZATION_ACTIVITY_TIME_MS = 92 [deprecated=true]; - PROVISIONING_NETWORK_TYPE = 93; - PROVISIONING_ACTION = 94; - PROVISIONING_EXTRAS = 95; - PROVISIONING_COPY_ACCOUNT_TASK_MS = 96; - PROVISIONING_CREATE_PROFILE_TASK_MS = 97; - PROVISIONING_START_PROFILE_TASK_MS = 98; - PROVISIONING_DOWNLOAD_PACKAGE_TASK_MS = 99; - PROVISIONING_INSTALL_PACKAGE_TASK_MS = 100; - PROVISIONING_CANCELLED = 101; - PROVISIONING_ERROR = 102; - PROVISIONING_COPY_ACCOUNT_STATUS = 103; - PROVISIONING_TOTAL_TASK_TIME_MS = 104; - PROVISIONING_SESSION_STARTED = 105; - PROVISIONING_SESSION_COMPLETED = 106; - PROVISIONING_TERMS_ACTIVITY_TIME_MS = 107; - PROVISIONING_TERMS_COUNT = 108; - PROVISIONING_TERMS_READ = 109; - - SEPARATE_PROFILE_CHALLENGE_CHANGED = 110; - SET_GLOBAL_SETTING = 111; - INSTALL_PACKAGE = 112; - UNINSTALL_PACKAGE = 113; - WIFI_SERVICE_ADD_NETWORK_SUGGESTIONS = 114; - WIFI_SERVICE_ADD_OR_UPDATE_NETWORK = 115; - QUERY_SUMMARY_FOR_DEVICE = 116; - REMOVE_CROSS_PROFILE_WIDGET_PROVIDER = 117; - ESTABLISH_VPN = 118; - SET_NETWORK_LOGGING_ENABLED = 119; - RETRIEVE_NETWORK_LOGS = 120; - PROVISIONING_PREPARE_TOTAL_TIME_MS = 121; - PROVISIONING_PREPARE_STARTED = 122; - PROVISIONING_PREPARE_COMPLETED = 123; - PROVISIONING_FLOW_TYPE = 124; - CROSS_PROFILE_APPS_GET_TARGET_USER_PROFILES = 125; - CROSS_PROFILE_APPS_START_ACTIVITY_AS_USER = 126; - SET_AUTO_TIME = 127; - SET_AUTO_TIME_ZONE = 128; - SET_USER_CONTROL_DISABLED_PACKAGES = 129; - SET_FACTORY_RESET_PROTECTION = 130; - SET_COMMON_CRITERIA_MODE = 131; - ALLOW_MODIFICATION_OF_ADMIN_CONFIGURED_NETWORKS = 132; - SET_TIME = 133; - SET_TIME_ZONE = 134; - SET_PERSONAL_APPS_SUSPENDED = 135; - SET_MANAGED_PROFILE_MAXIMUM_TIME_OFF = 136; - COMP_TO_ORG_OWNED_PO_MIGRATED = 137; - SET_CROSS_PROFILE_PACKAGES = 138; - SET_INTERACT_ACROSS_PROFILES_APP_OP = 139; - GET_CROSS_PROFILE_PACKAGES = 140; - CAN_REQUEST_INTERACT_ACROSS_PROFILES_TRUE = 141; - CAN_REQUEST_INTERACT_ACROSS_PROFILES_FALSE_NO_PROFILES = 142; - CAN_REQUEST_INTERACT_ACROSS_PROFILES_FALSE_WHITELIST = 143; - CAN_REQUEST_INTERACT_ACROSS_PROFILES_FALSE_PERMISSION = 144; - CAN_INTERACT_ACROSS_PROFILES_TRUE = 145; - CAN_INTERACT_ACROSS_PROFILES_FALSE_PERMISSION = 146; - CAN_INTERACT_ACROSS_PROFILES_FALSE_NO_PROFILES = 147; - CREATE_CROSS_PROFILE_INTENT = 148; - IS_MANAGED_PROFILE = 149; - START_ACTIVITY_BY_INTENT = 150; - BIND_CROSS_PROFILE_SERVICE = 151; - PROVISIONING_DPC_SETUP_STARTED = 152; - PROVISIONING_DPC_SETUP_COMPLETED = 153; - PROVISIONING_ORGANIZATION_OWNED_MANAGED_PROFILE = 154; - RESOLVER_CROSS_PROFILE_TARGET_OPENED = 155; - RESOLVER_SWITCH_TABS = 156; - RESOLVER_EMPTY_STATE_WORK_APPS_DISABLED = 157; - RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL= 158; - RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK= 159; - RESOLVER_EMPTY_STATE_NO_APPS_RESOLVED= 160; - RESOLVER_AUTOLAUNCH_CROSS_PROFILE_TARGET = 161; - CROSS_PROFILE_SETTINGS_PAGE_LAUNCHED_FROM_APP = 162; - CROSS_PROFILE_SETTINGS_PAGE_LAUNCHED_FROM_SETTINGS = 163; - CROSS_PROFILE_SETTINGS_PAGE_ADMIN_RESTRICTED = 164; - CROSS_PROFILE_SETTINGS_PAGE_MISSING_WORK_APP = 165; - CROSS_PROFILE_SETTINGS_PAGE_MISSING_PERSONAL_APP = 166; - CROSS_PROFILE_SETTINGS_PAGE_MISSING_INSTALL_BANNER_INTENT = 167; - CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_CLICKED = 168; - CROSS_PROFILE_SETTINGS_PAGE_INSTALL_BANNER_NO_INTENT_CLICKED = 169; - CROSS_PROFILE_SETTINGS_PAGE_USER_CONSENTED = 170; - CROSS_PROFILE_SETTINGS_PAGE_USER_DECLINED_CONSENT = 171; - CROSS_PROFILE_SETTINGS_PAGE_PERMISSION_REVOKED = 172; - DOCSUI_EMPTY_STATE_NO_PERMISSION = 173; - DOCSUI_EMPTY_STATE_QUIET_MODE = 174; - DOCSUI_LAUNCH_OTHER_APP = 175; - DOCSUI_PICK_RESULT = 176; -} diff --git a/core/proto/android/stats/devicepolicy/jarjar-rules.txt b/core/proto/android/stats/devicepolicy/jarjar-rules.txt deleted file mode 100644 index 40043a861ceb..000000000000 --- a/core/proto/android/stats/devicepolicy/jarjar-rules.txt +++ /dev/null @@ -1 +0,0 @@ -rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1 diff --git a/core/proto/android/stats/dnsresolver/Android.bp b/core/proto/android/stats/dnsresolver/Android.bp deleted file mode 100644 index 1e8c76314448..000000000000 --- a/core/proto/android/stats/dnsresolver/Android.bp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library_static { - name: "dnsresolverprotosnano", - proto: { - type: "nano", - }, - srcs: [ - "dns_resolver.proto", - ], - sdk_version: "system_current", -} diff --git a/core/proto/android/stats/dnsresolver/dns_resolver.proto b/core/proto/android/stats/dnsresolver/dns_resolver.proto deleted file mode 100644 index b17d12c9c315..000000000000 --- a/core/proto/android/stats/dnsresolver/dns_resolver.proto +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ -syntax = "proto2"; -package android.stats.dnsresolver; - -enum EventType { - EVENT_UNKNOWN = 0; - EVENT_GETADDRINFO = 1; - EVENT_GETHOSTBYNAME = 2; - EVENT_GETHOSTBYADDR = 3; - EVENT_RES_NSEND = 4; -} - -// The return value of the DNS resolver for each DNS lookups. -// bionic/libc/include/netdb.h -// system/netd/resolv/include/netd_resolv/resolv.h -enum ReturnCode { - RC_EAI_NO_ERROR = 0; - RC_EAI_ADDRFAMILY = 1; - RC_EAI_AGAIN = 2; - RC_EAI_BADFLAGS = 3; - RC_EAI_FAIL = 4; - RC_EAI_FAMILY = 5; - RC_EAI_MEMORY = 6; - RC_EAI_NODATA = 7; - RC_EAI_NONAME = 8; - RC_EAI_SERVICE = 9; - RC_EAI_SOCKTYPE = 10; - RC_EAI_SYSTEM = 11; - RC_EAI_BADHINTS = 12; - RC_EAI_PROTOCOL = 13; - RC_EAI_OVERFLOW = 14; - RC_RESOLV_INTERNAL_ERROR = 254; - RC_RESOLV_TIMEOUT = 255; - RC_EAI_MAX = 256; -} - -enum NsRcode { - NS_R_NO_ERROR = 0; // No error occurred. - NS_R_FORMERR = 1; // Format error. - NS_R_SERVFAIL = 2; // Server failure. - NS_R_NXDOMAIN = 3; // Name error. - NS_R_NOTIMPL = 4; // Unimplemented. - NS_R_REFUSED = 5; // Operation refused. - // these are for BIND_UPDATE - NS_R_YXDOMAIN = 6; // Name exists - NS_R_YXRRSET = 7; // RRset exists - NS_R_NXRRSET = 8; // RRset does not exist - NS_R_NOTAUTH = 9; // Not authoritative for zone - NS_R_NOTZONE = 10; // Zone of record different from zone section - NS_R_MAX = 11; - // Define rcode=12~15(UNASSIGNED) in rcode enum type. - // Some DNS Servers might return undefined code to devices. - // Without the enum definition, that would be noise for our dashboard. - NS_R_UNASSIGNED12 = 12; // Unassigned - NS_R_UNASSIGNED13 = 13; // Unassigned - NS_R_UNASSIGNED14 = 14; // Unassigned - NS_R_UNASSIGNED15 = 15; // Unassigned - // The following are EDNS extended rcodes - NS_R_BADVERS = 16; - // The following are TSIG errors - // NS_R_BADSIG = 16, - NS_R_BADKEY = 17; - NS_R_BADTIME = 18; - NS_R_INTERNAL_ERROR = 254; - NS_R_TIMEOUT = 255; -} - -// Currently defined type values for resources and queries. -enum NsType { - NS_T_INVALID = 0; // Cookie. - NS_T_A = 1; // Host address. - NS_T_NS = 2; // Authoritative server. - NS_T_MD = 3; // Mail destination. - NS_T_MF = 4; // Mail forwarder. - NS_T_CNAME = 5; // Canonical name. - NS_T_SOA = 6; // Start of authority zone. - NS_T_MB = 7; // Mailbox domain name. - NS_T_MG = 8; // Mail group member. - NS_T_MR = 9; // Mail rename name. - NS_T_NULL = 10; // Null resource record. - NS_T_WKS = 11; // Well known service. - NS_T_PTR = 12; // Domain name pointer. - NS_T_HINFO = 13; // Host information. - NS_T_MINFO = 14; // Mailbox information. - NS_T_MX = 15; // Mail routing information. - NS_T_TXT = 16; // Text strings. - NS_T_RP = 17; // Responsible person. - NS_T_AFSDB = 18; // AFS cell database. - NS_T_X25 = 19; // X_25 calling address. - NS_T_ISDN = 20; // ISDN calling address. - NS_T_RT = 21; // Router. - NS_T_NSAP = 22; // NSAP address. - NS_T_NSAP_PTR = 23; // Reverse NSAP lookup (deprecated). - NS_T_SIG = 24; // Security signature. - NS_T_KEY = 25; // Security key. - NS_T_PX = 26; // X.400 mail mapping. - NS_T_GPOS = 27; // Geographical position (withdrawn). - NS_T_AAAA = 28; // IPv6 Address. - NS_T_LOC = 29; // Location Information. - NS_T_NXT = 30; // Next domain (security). - NS_T_EID = 31; // Endpoint identifier. - NS_T_NIMLOC = 32; // Nimrod Locator. - NS_T_SRV = 33; // Server Selection. - NS_T_ATMA = 34; // ATM Address - NS_T_NAPTR = 35; // Naming Authority PoinTeR - NS_T_KX = 36; // Key Exchange - NS_T_CERT = 37; // Certification record - NS_T_A6 = 38; // IPv6 address (experimental) - NS_T_DNAME = 39; // Non-terminal DNAME - NS_T_SINK = 40; // Kitchen sink (experimentatl) - NS_T_OPT = 41; // EDNS0 option (meta-RR) - NS_T_APL = 42; // Address prefix list (RFC 3123) - NS_T_DS = 43; // Delegation Signer - NS_T_SSHFP = 44; // SSH Fingerprint - NS_T_IPSECKEY = 45; // IPSEC Key - NS_T_RRSIG = 46; // RRset Signature - NS_T_NSEC = 47; // Negative security - NS_T_DNSKEY = 48; // DNS Key - NS_T_DHCID = 49; // Dynamic host configuratin identifier - NS_T_NSEC3 = 50; // Negative security type 3 - NS_T_NSEC3PARAM = 51; // Negative security type 3 parameters - NS_T_HIP = 55; // Host Identity Protocol - NS_T_SPF = 99; // Sender Policy Framework - NS_T_TKEY = 249; // Transaction key - NS_T_TSIG = 250; // Transaction signature. - NS_T_IXFR = 251; // Incremental zone transfer. - NS_T_AXFR = 252; // Transfer zone of authority. - NS_T_MAILB = 253; // Transfer mailbox records. - NS_T_MAILA = 254; // Transfer mail agent records. - NS_T_ANY = 255; // Wildcard match. - NS_T_ZXFR = 256; // BIND-specific, nonstandard. - NS_T_DLV = 32769; // DNSSEC look-aside validatation. - NS_T_MAX = 65536; -} - -enum IpVersion { - IV_UNKNOWN = 0; - IV_IPV4 = 1; - IV_IPV6 = 2; -} - -enum Protocol { - PROTO_UNKNOWN = 0; - PROTO_UDP = 1; - PROTO_TCP = 2; - PROTO_DOT = 3; -} - -enum PrivateDnsModes { - PDM_UNKNOWN = 0; - PDM_OFF = 1; - PDM_OPPORTUNISTIC = 2; - PDM_STRICT = 3; -} - -enum NetworkType { - NT_UNKNOWN = 0; - // Indicates this network uses a Cellular transport. - NT_CELLULAR = 1; - // Indicates this network uses a Wi-Fi transport. - NT_WIFI = 2; - // Indicates this network uses a Bluetooth transport. - NT_BLUETOOTH = 3; - // Indicates this network uses an Ethernet transport. - NT_ETHERNET = 4; - // Indicates this network uses a VPN transport, now deprecated. - NT_VPN = 5 [deprecated=true]; - // Indicates this network uses a Wi-Fi Aware transport. - NT_WIFI_AWARE = 6; - // Indicates this network uses a LoWPAN transport. - NT_LOWPAN = 7; - // Indicates this network uses a Cellular+VPN transport. - NT_CELLULAR_VPN = 8; - // Indicates this network uses a Wi-Fi+VPN transport. - NT_WIFI_VPN = 9; - // Indicates this network uses a Bluetooth+VPN transport. - NT_BLUETOOTH_VPN = 10; - // Indicates this network uses an Ethernet+VPN transport. - NT_ETHERNET_VPN = 11; - // Indicates this network uses a Wi-Fi+Cellular+VPN transport. - NT_WIFI_CELLULAR_VPN = 12; -} - -enum CacheStatus{ - // the cache can't handle that kind of queries. - // or the answer buffer is too small. - CS_UNSUPPORTED = 0; - // the cache doesn't know about this query. - CS_NOTFOUND = 1; - // the cache found the answer. - CS_FOUND = 2; - // Don't do anything on cache. - CS_SKIP = 3; -} - -// The enum LinuxErrno is defined in the following 2 files. -// 1. bionic/libc/kernel/uapi/asm-generic/errno-base.h -// 2. bionic/libc/kernel/uapi/asm-generic/errno.h -enum LinuxErrno { - SYS_NO_ERROR = 0; - SYS_EPERM = 1; // Not super-user - SYS_ENOENT = 2; // No such file or directory - SYS_ESRCH = 3; // No such process - SYS_EINTR = 4; // Interrupted system call - SYS_EIO = 5; // I/O error - SYS_ENXIO = 6; // No such device or address - SYS_E2BIG = 7; // Arg list too long - SYS_ENOEXEC = 8; // Exec format error - SYS_EBADF = 9; // Bad file number - SYS_ECHILD = 10; // No children - SYS_EAGAIN = 11; // No more processes - SYS_ENOMEM = 12; // Not enough core - SYS_EACCES = 13; // Permission denied - SYS_EFAULT = 14; // Bad address - SYS_ENOTBLK = 15; // Block device required - SYS_EBUSY = 16; // Mount device busy - SYS_EEXIST = 17; // File exists - SYS_EXDEV = 18; // Cross-device link - SYS_ENODEV = 19; // No such device - SYS_ENOTDIR = 20; // Not a directory - SYS_EISDIR = 21; // Is a directory - SYS_EINVAL = 22; // Invalid argument - SYS_ENFILE = 23; // Too many open files in system - SYS_EMFILE = 24; // Too many open files - SYS_ENOTTY = 25; // Not a typewriter - SYS_ETXTBSY = 26; // Text file busy - SYS_EFBIG = 27; // File too large - SYS_ENOSPC = 28; // No space left on device - SYS_ESPIPE = 29; // Illegal seek - SYS_EROFS = 30; // Read only file system - SYS_EMLINK = 31; // Too many links - SYS_EPIPE = 32; // Broken pipe - SYS_EDOM = 33; // Math arg out of domain of func - SYS_ERANGE = 34; // Math result not representable - SYS_EDEADLOCK = 35; // File locking deadlock error - SYS_ENAMETOOLONG = 36; // File or path name too long - SYS_ENOLCK = 37; // No record locks available - SYS_ENOSYS = 38; // Function not implemented - SYS_ENOTEMPTY = 39; // Directory not empty - SYS_ELOOP = 40; // Too many symbolic links - SYS_ENOMSG = 42; // No message of desired type - SYS_EIDRM = 43; // Identifier removed - SYS_ECHRNG = 44; // Channel number out of range - SYS_EL2NSYNC = 45; // Level 2 not synchronized - SYS_EL3HLT = 46; // Level 3 halted - SYS_EL3RST = 47; // Level 3 reset - SYS_ELNRNG = 48; // Link number out of range - SYS_EUNATCH = 49; // rotocol driver not attached - SYS_ENOCSI = 50; // No CSI structure available - SYS_EL2HLT = 51; // Level 2 halted - SYS_EBADE = 52; // Invalid exchange - SYS_EBADR = 53; // Invalid request descriptor - SYS_EXFULL = 54; // Exchange full - SYS_ENOANO = 55; // No anode - SYS_EBADRQC = 56; // Invalid request code - SYS_EBADSLT = 57; // Invalid slot - SYS_EBFONT = 59; // Bad font file fmt - SYS_ENOSTR = 60; // Device not a stream - SYS_ENODATA = 61; // No data (for no delay io) - SYS_ETIME = 62; // Timer expired - SYS_ENOSR = 63; // Out of streams resources - SYS_ENONET = 64; // Machine is not on the network - SYS_ENOPKG = 65; // Package not installed - SYS_EREMOTE = 66; // The object is remote - SYS_ENOLINK = 67; // The link has been severed - SYS_EADV = 68; // Advertise error - SYS_ESRMNT = 69; // Srmount error - SYS_ECOMM = 70; // Communication error on send - SYS_EPROTO = 71; // Protocol error - SYS_EMULTIHOP = 72; // Multihop attempted - SYS_EDOTDOT = 73; // Cross mount point (not really error) - SYS_EBADMSG = 74; // Trying to read unreadable message - SYS_EOVERFLOW = 75; // Value too large for defined data type - SYS_ENOTUNIQ = 76; // Given log. name not unique - SYS_EBADFD = 77; // f.d. invalid for this operation - SYS_EREMCHG = 78; // Remote address changed - SYS_ELIBACC = 79; // Can't access a needed shared lib - SYS_ELIBBAD = 80; // Accessing a corrupted shared lib - SYS_ELIBSCN = 81; // .lib section in a.out corrupted - SYS_ELIBMAX = 82; // Attempting to link in too many libs - SYS_ELIBEXEC = 83; // Attempting to exec a shared library - SYS_EILSEQ = 84; - SYS_ERESTART = 85; - SYS_ESTRPIPE = 86; - SYS_EUSERS = 87; - SYS_ENOTSOCK = 88; // Socket operation on non-socket - SYS_EDESTADDRREQ = 89; // Destination address required - SYS_EMSGSIZE = 90; // Message too long - SYS_EPROTOTYPE = 91; // Protocol wrong type for socket - SYS_ENOPROTOOPT = 92; // Protocol not available - SYS_EPROTONOSUPPORT = 93; // Unknown protocol - SYS_ESOCKTNOSUPPORT = 94; // Socket type not supported - SYS_EOPNOTSUPP = 95; // Operation not supported on transport endpoint - SYS_EPFNOSUPPORT = 96; // Protocol family not supported - SYS_EAFNOSUPPORT = 97; // Address family not supported by protocol family - SYS_EADDRINUSE = 98; // Address already in use - SYS_EADDRNOTAVAIL = 99; // Address not available - SYS_ENETDOWN = 100; // Network interface is not configured - SYS_ENETUNREACH = 101; // Network is unreachable - SYS_ENETRESET = 102; - SYS_ECONNABORTED = 103; // Connection aborted - SYS_ECONNRESET = 104; // Connection reset by peer - SYS_ENOBUFS = 105; // No buffer space available - SYS_EISCONN = 106; // Socket is already connected - SYS_ENOTCONN = 107; // Socket is not connected - SYS_ESHUTDOWN = 108; // Can't send after socket shutdown - SYS_ETOOMANYREFS = 109; - SYS_ETIMEDOUT = 110; // Connection timed out - SYS_ECONNREFUSED = 111; // Connection refused - SYS_EHOSTDOWN = 112; // Host is down - SYS_EHOSTUNREACH = 113; // Host is unreachable - SYS_EALREADY = 114; // Socket already connected - SYS_EINPROGRESS = 115; // Connection already in progress - SYS_ESTALE = 116; - SYS_EUCLEAN = 117; - SYS_ENOTNAM = 118; - SYS_ENAVAIL = 119; - SYS_EISNAM = 120; - SYS_EREMOTEIO = 121; - SYS_EDQUOT = 122; - SYS_ENOMEDIUM = 123; // No medium (in tape drive) - SYS_EMEDIUMTYPE = 124; - SYS_ECANCELED = 125; - SYS_ENOKEY = 126; - SYS_EKEYEXPIRED = 127; - SYS_EKEYREVOKED = 128; - SYS_EKEYREJECTED = 129; - SYS_EOWNERDEAD = 130; - SYS_ENOTRECOVERABLE = 131; - SYS_ERFKILL = 132; - SYS_EHWPOISON = 133; -} - -message DnsQueryEvent { - optional android.stats.dnsresolver.NsRcode rcode = 1; - - optional android.stats.dnsresolver.NsType type = 2; - - optional android.stats.dnsresolver.CacheStatus cache_hit = 3; - - optional android.stats.dnsresolver.IpVersion ip_version = 4; - - optional android.stats.dnsresolver.Protocol protocol = 5; - - // Number of DNS query retry times - optional int32 retry_times = 6; - - // Ordinal number of name server. - optional int32 dns_server_index = 7; - - // Used only by TCP and DOT. True for new connections. - optional bool connected = 8; - - optional int32 latency_micros = 9; - - optional android.stats.dnsresolver.LinuxErrno linux_errno = 10; -} - -message DnsQueryEvents { - repeated DnsQueryEvent dns_query_event = 1; -} diff --git a/core/proto/android/stats/docsui/docsui_enums.proto b/core/proto/android/stats/docsui/docsui_enums.proto deleted file mode 100644 index 5963f6a7f938..000000000000 --- a/core/proto/android/stats/docsui/docsui_enums.proto +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.stats.docsui; -option java_multiple_files = true; - -enum LaunchAction { - UNKNOWN = 0; - OPEN = 1; - CREATE = 2; - GET_CONTENT = 3; - OPEN_TREE = 4; - PICK_COPY_DEST = 5; - BROWSE = 6; - OTHER = 7; -} - -enum MimeType { - MIME_UNKNOWN = 0; - MIME_NONE = 1; - MIME_ANY = 2; - MIME_APPLICATION = 3; - MIME_AUDIO = 4; - MIME_IMAGE = 5; - MIME_MESSAGE = 6; - MIME_MULTIPART = 7; - MIME_TEXT = 8; - MIME_VIDEO = 9; - MIME_OTHER = 10; -} - -enum Root { - ROOT_UNKNOWN = 0; - ROOT_NONE = 1; - ROOT_OTHER_DOCS_PROVIDER = 2; - ROOT_AUDIO = 3; - ROOT_DEVICE_STORAGE = 4; - ROOT_DOWNLOADS = 5; - ROOT_HOME = 6; - ROOT_IMAGES = 7; - ROOT_RECENTS = 8; - ROOT_VIDEOS = 9; - ROOT_MTP = 10; - ROOT_THIRD_PARTY_APP = 11; - ROOT_DOCUMENTS = 12; -} - -enum ContextScope { - SCOPE_UNKNOWN = 0; - SCOPE_FILES = 1; - SCOPE_PICKER = 2; -} - -enum Provider { - PROVIDER_UNKNOWN = 0; - PROVIDER_SYSTEM = 1; - PROVIDER_EXTERNAL = 2; -} - -enum FileOperation { - OP_UNKNOWN = 0; - OP_OTHER = 1; - OP_COPY = 2; - OP_COPY_INTRA_PROVIDER = 3; - OP_COPY_SYSTEM_PROVIDER = 4; - OP_COPY_EXTERNAL_PROVIDER = 5; - OP_MOVE = 6; - OP_MOVE_INTRA_PROVIDER = 7; - OP_MOVE_SYSTEM_PROVIDER = 8; - OP_MOVE_EXTERNAL_PROVIDER = 9; - OP_DELETE = 10; - OP_RENAME = 11; - OP_CREATE_DIR = 12; - OP_OTHER_ERROR = 13; - OP_DELETE_ERROR = 14; - OP_MOVE_ERROR = 15; - OP_COPY_ERROR = 16; - OP_RENAME_ERROR = 17; - OP_CREATE_DIR_ERROR = 18; - OP_COMPRESS_INTRA_PROVIDER = 19; - OP_COMPRESS_SYSTEM_PROVIDER = 20; - OP_COMPRESS_EXTERNAL_PROVIDER = 21; - OP_EXTRACT_INTRA_PROVIDER = 22; - OP_EXTRACT_SYSTEM_PROVIDER = 23; - OP_EXTRACT_EXTERNAL_PROVIDER = 24; - OP_COMPRESS_ERROR = 25; - OP_EXTRACT_ERROR = 26; -} - -enum SubFileOperation { - SUB_OP_UNKNOWN = 0; - SUB_OP_QUERY_DOC = 1; - SUB_OP_QUERY_CHILD = 2; - SUB_OP_OPEN_FILE = 3; - SUB_OP_READ_FILE = 4; - SUB_OP_CREATE_DOC = 5; - SUB_OP_WRITE_FILE = 6; - SUB_OP_DELETE_DOC = 7; - SUB_OP_OBTAIN_STREAM_TYPE = 8; - SUB_OP_QUICK_MOVE = 9; - SUB_OP_QUICK_COPY = 10; -} - -enum CopyMoveOpMode { - MODE_UNKNOWN = 0; - MODE_PROVIDER = 1; - MODE_CONVERTED = 2; - MODE_CONVENTIONAL = 3; -} - -enum Authority { - AUTH_UNKNOWN = 0; - AUTH_OTHER = 1; - AUTH_MEDIA = 2; - AUTH_STORAGE_INTERNAL = 3; - AUTH_STORAGE_EXTERNAL = 4; - AUTH_DOWNLOADS = 5; - AUTH_MTP = 6; -} - -enum UserAction { - ACTION_UNKNOWN = 0; - ACTION_OTHER = 1; - ACTION_GRID = 2; - ACTION_LIST = 3; - ACTION_SORT_NAME = 4; - ACTION_SORT_DATE = 5; - ACTION_SORT_SIZE = 6; - ACTION_SORT_TYPE = 7; - ACTION_SEARCH = 8; - ACTION_SHOW_SIZE = 9; - ACTION_HIDE_SIZE = 10; - ACTION_SETTINGS = 11; - ACTION_COPY_TO = 12; - ACTION_MOVE_TO = 13; - ACTION_DELETE = 14; - ACTION_RENAME = 15; - ACTION_CREATE_DIR = 16; - ACTION_SELECT_ALL = 17; - ACTION_SHARE = 18; - ACTION_OPEN = 19; - ACTION_SHOW_ADVANCED = 20; - ACTION_HIDE_ADVANCED = 21; - ACTION_NEW_WINDOW = 22; - ACTION_PASTE_CLIPBOARD = 23; - ACTION_COPY_CLIPBOARD = 24; - ACTION_DRAG_N_DROP = 25; - ACTION_DRAG_N_DROP_MULTI_WINDOW = 26; - ACTION_CUT_CLIPBOARD = 27; - ACTION_COMPRESS = 28; - ACTION_EXTRACT_TO = 29; - ACTION_VIEW_IN_APPLICATION = 30; - ACTION_INSPECTOR = 31; - ACTION_SEARCH_CHIP = 32; - ACTION_SEARCH_HISTORY = 33; -} - -enum InvalidScopedAccess { - SCOPED_DIR_ACCESS_UNKNOWN = 0; - SCOPED_DIR_ACCESS_INVALID_ARGUMENTS = 1; - SCOPED_DIR_ACCESS_INVALID_DIRECTORY = 2; - SCOPED_DIR_ACCESS_ERROR = 3; - SCOPED_DIR_ACCESS_DEPRECATED = 4; -} - -enum SearchType { - TYPE_UNKNOWN = 0; - TYPE_CHIP_IMAGES = 1; - TYPE_CHIP_AUDIOS = 2; - TYPE_CHIP_VIDEOS = 3; - TYPE_CHIP_DOCS = 4; - TYPE_SEARCH_HISTORY = 5; - TYPE_SEARCH_STRING = 6; - TYPE_CHIP_LARGE_FILES = 7; - TYPE_CHIP_FROM_THIS_WEEK = 8; -} - -enum SearchMode { - SEARCH_UNKNOWN = 0; - SEARCH_KEYWORD = 1; - SEARCH_CHIPS = 2; - SEARCH_KEYWORD_N_CHIPS = 3; -} diff --git a/core/proto/android/stats/hdmi/enums.proto b/core/proto/android/stats/hdmi/enums.proto deleted file mode 100644 index acb8899fbdd9..000000000000 --- a/core/proto/android/stats/hdmi/enums.proto +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.stats.hdmi; -option java_multiple_files = true; -option java_outer_classname = "HdmiStatsEnums"; - -// HDMI CEC logical addresses. -// Values correspond to "CEC Table 5 Logical Addresses" in the HDMI CEC 1.4b spec. -enum LogicalAddress { - LOGICAL_ADDRESS_UNKNOWN = -1; - TV = 0; - RECORDING_DEVICE_1 = 1; - RECORDING_DEVICE_2 = 2; - TUNER_1 = 3; - PLAYBACK_DEVICE_1 = 4; - AUDIO_SYSTEM = 5; - TUNER_2 = 6; - TUNER_3 = 7; - PLAYBACK_DEVICE_2 = 8; - RECORDING_DEVICE_3 = 9; - TUNER_4 = 10; - PLAYBACK_DEVICE_3 = 11; - RESERVED_1 = 12; - RESERVED_2 = 13; - SPECIFIC_USE = 14; - UNREGISTERED_OR_BROADCAST = 15; -} - -// The relationship between two paths. -// Values correspond exactly to PathRelationship in com.android.server.hdmi.Constants. -enum PathRelationship { - RELATIONSHIP_TO_ACTIVE_SOURCE_UNKNOWN = 0; - DIFFERENT_BRANCH = 1; - ANCESTOR = 2; - DESCENDANT = 3; - SIBLING = 4; - SAME = 5; -} - -// The result of attempting to send a HDMI CEC message. -// Values correspond to the constants in android.hardware.tv.cec.V1_0.SendMessageResult, -// offset by 10. -enum SendMessageResult { - SEND_MESSAGE_RESULT_UNKNOWN = 0; - SUCCESS = 10; - NACK = 11; - BUSY = 12; - FAIL = 13; -} - -// Whether a HDMI CEC message is sent from this device, to this device, or neither. -enum MessageDirection { - MESSAGE_DIRECTION_UNKNOWN = 0; - MESSAGE_DIRECTION_OTHER = 1; // None of the other options. - OUTGOING = 2; // Sent from this device. - INCOMING = 3; // Sent to this device. - TO_SELF = 4; // Sent from this device, to this device. Indicates a bug. -} - -// User control commands. Each value can represent an individual command, or a set of commands. -// Values correspond to "CEC Table 30 UI Command Codes" in the HDMI CEC 1.4b spec, offset by 0x100. -enum UserControlPressedCommand { - USER_CONTROL_PRESSED_COMMAND_UNKNOWN = 0; - - // Represents all codes that are not represented by another value. - USER_CONTROL_PRESSED_COMMAND_OTHER = 1; - - // Represents all number codes (codes 0x1E through 0x29). - NUMBER = 2; - - // Navigation - SELECT = 0x100; - UP = 0x101; - DOWN = 0x102; - LEFT = 0x103; - RIGHT = 0x104; - RIGHT_UP = 0x105; - RIGHT_DOWN = 0x106; - LEFT_UP = 0x107; - LEFT_DOWN = 0x108; - EXIT = 0x10D; - - // Volume - VOLUME_UP = 0x141; - VOLUME_DOWN = 0x142; - VOLUME_MUTE = 0x143; - - // Power - POWER = 0x140; - POWER_TOGGLE = 0x16B; - POWER_OFF = 0x16C; - POWER_ON = 0x16D; -} - -// Reason parameter of the <Feature Abort> message. -// Values correspond to "CEC Table 29 Operand Descriptions" in the HDMI CEC 1.4b spec, -// offset by 10. -enum FeatureAbortReason { - FEATURE_ABORT_REASON_UNKNOWN = 0; - UNRECOGNIZED_OPCODE = 10; - NOT_IN_CORRECT_MODE_TO_RESPOND = 11; - CANNOT_PROVIDE_SOURCE = 12; - INVALID_OPERAND = 13; - REFUSED = 14; - UNABLE_TO_DETERMINE = 15; -}
\ No newline at end of file diff --git a/core/proto/android/stats/intelligence/enums.proto b/core/proto/android/stats/intelligence/enums.proto deleted file mode 100644 index 0c210e3fd08f..000000000000 --- a/core/proto/android/stats/intelligence/enums.proto +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; - -package android.stats.intelligence; -option java_outer_classname = "IntelligenceStatsEnums"; - -enum Status { - // The value wasn't set. - // protoc requires enum values to be unique by package rather than enum type. - // This forces us to prefix the enum values. - STATUS_UNKNOWN = 0; - // The event succeeded. - STATUS_SUCCEEDED = 1; - // The event had an error. - STATUS_FAILED = 2; -} - -enum EventType { - // The value wasn't set. - EVENT_UNKNOWN = 0; - // ContentSuggestionsService classifyContentSelections call. - EVENT_CONTENT_SUGGESTIONS_CLASSIFY_CONTENT_CALL = 1; - // ContentSuggestionsService suggestContentSelections call. - EVENT_CONTENT_SUGGESTIONS_SUGGEST_CONTENT_CALL = 2; -} diff --git a/core/proto/android/stats/launcher/Android.bp b/core/proto/android/stats/launcher/Android.bp deleted file mode 100644 index 976a0b8634a3..000000000000 --- a/core/proto/android/stats/launcher/Android.bp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2018 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library { - name: "launcherprotosnano", - proto: { - type: "nano", - output_params: ["store_unknown_fields=true"], - include_dirs: ["external/protobuf/src"], - }, - - sdk_version: "current", - srcs: [ - "*.proto", - ], -} - -java_library { - name: "launcherprotoslite", - proto: { - type: "lite", - include_dirs: ["external/protobuf/src"], - }, - - sdk_version: "current", - srcs: [ - "*.proto", - ], -} diff --git a/core/proto/android/stats/launcher/launcher.proto b/core/proto/android/stats/launcher/launcher.proto deleted file mode 100644 index fc177d57b193..000000000000 --- a/core/proto/android/stats/launcher/launcher.proto +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.stats.launcher; -option java_multiple_files = true; - -enum LauncherAction { - DEFAULT_ACTION = 0; - LAUNCH_APP = 1; - LAUNCH_TASK = 2; - DISMISS_TASK = 3; - LONGPRESS = 4; - DRAGDROP = 5; - SWIPE_UP = 6; - SWIPE_DOWN = 7; - SWIPE_LEFT = 8; - SWIPE_RIGHT = 9; -} - -enum LauncherState { - LAUNCHER_STATE_UNSPECIFIED = 0; - BACKGROUND = 1; - HOME = 2; - OVERVIEW = 3; - ALLAPPS = 4; - UNCHANGED = 5; -} - -message LauncherTarget { - enum Type { - NONE = 0; - ITEM_TYPE = 1; - CONTROL_TYPE = 2; - CONTAINER_TYPE = 3; - } - enum Item { - DEFAULT_ITEM = 0; - APP_ICON = 1; - SHORTCUT = 2; - WIDGET = 3; - FOLDER_ICON = 4; - DEEPSHORTCUT = 5; - SEARCHBOX = 6; - EDITTEXT = 7; - NOTIFICATION = 8; - TASK = 9; - } - enum Container { - DEFAULT_CONTAINER = 0; - HOTSEAT = 1; - FOLDER = 2; - PREDICTION = 3; - SEARCHRESULT = 4; - } - enum Control { - DEFAULT_CONTROL = 0; - MENU = 1; - UNINSTALL = 2; - REMOVE = 3; - } - optional Type type = 1; - optional Item item = 2; - optional Container container = 3; - optional Control control = 4; - optional string launch_component = 5; - optional int32 page_id = 6; - optional int32 grid_x = 7; - optional int32 grid_y = 8; -} - -message LauncherExtension { - repeated LauncherTarget src_target = 1; - repeated LauncherTarget dst_target = 2; -} diff --git a/core/proto/android/stats/location/location_enums.proto b/core/proto/android/stats/location/location_enums.proto deleted file mode 100644 index 553c01c5d0dd..000000000000 --- a/core/proto/android/stats/location/location_enums.proto +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; - -package android.stats.location; -option java_outer_classname = "LocationStatsEnums"; - - -// APIs from LocationManagerService -enum LocationManagerServiceApi { - API_UNKNOWN = 0; - API_REQUEST_LOCATION_UPDATES = 1; - API_ADD_GNSS_MEASUREMENTS_LISTENER = 2; - API_REGISTER_GNSS_STATUS_CALLBACK = 3; - API_REQUEST_GEOFENCE = 4; - API_SEND_EXTRA_COMMAND = 5; -} - -enum UsageState { - USAGE_STARTED = 0; - USAGE_ENDED = 1; -} - -// Type of location providers -enum ProviderType { - PROVIDER_UNKNOWN = 0; - PROVIDER_NETWORK = 1; - PROVIDER_GPS = 2; - PROVIDER_PASSIVE = 3; - PROVIDER_FUSED = 4; -} - -// Type of Callback passed in for this API -enum CallbackType { - CALLBACK_UNKNOWN = 0; - // Current API does not need a callback, e.g. sendExtraCommand - CALLBACK_NOT_APPLICABLE = 1; - CALLBACK_LISTENER = 2; - CALLBACK_PENDING_INTENT = 3; -} - -// Possible values for mQuality field in -// frameworks/base/location/java/android/location/LocationRequest.java -enum LocationRequestQuality { - QUALITY_UNKNOWN = 0; - ACCURACY_FINE = 100; - ACCURACY_BLOCK = 102; - ACCURACY_CITY = 104; - POWER_NONE = 200; - POWER_LOW = 201; - POWER_HIGH = 203; -} - -// Bucketized values for interval field in -// frameworks/base/location/java/android/location/LocationRequest.java -enum LocationRequestIntervalBucket { - INTERVAL_UNKNOWN = 0; - INTERVAL_BETWEEN_0_SEC_AND_1_SEC = 1; - INTERVAL_BETWEEN_1_SEC_AND_5_SEC = 2; - INTERVAL_BETWEEN_5_SEC_AND_1_MIN = 3; - INTERVAL_BETWEEN_1_MIN_AND_10_MIN = 4; - INTERVAL_BETWEEN_10_MIN_AND_1_HOUR = 5; - INTERVAL_LARGER_THAN_1_HOUR = 6; -} - -// Bucketized values for small displacement field in -// frameworks/base/location/java/android/location/LocationRequest.java -// Value in meters. -enum SmallestDisplacementBucket { - DISTANCE_UNKNOWN = 0; - DISTANCE_ZERO = 1; - DISTANCE_BETWEEN_0_AND_100 = 2; - DISTANCE_LARGER_THAN_100 = 3; -} - -// Bucketized values for expire_in field in -// frameworks/base/location/java/android/location/LocationRequest.java -enum ExpirationBucket { - EXPIRATION_UNKNOWN = 0; - EXPIRATION_BETWEEN_0_AND_20_SEC = 1; - EXPIRATION_BETWEEN_20_SEC_AND_1_MIN = 2; - EXPIRATION_BETWEEN_1_MIN_AND_10_MIN = 3; - EXPIRATION_BETWEEN_10_MIN_AND_1_HOUR = 4; - EXPIRATION_LARGER_THAN_1_HOUR = 5; - EXPIRATION_NO_EXPIRY = 6; -} - -// Bucketized values for radius field in -// frameworks/base/location/java/android/location/Geofence.java -// Value in meters. -enum GeofenceRadiusBucket { - RADIUS_UNKNOWN = 0; - RADIUS_BETWEEN_0_AND_100 = 1; - RADIUS_BETWEEN_100_AND_200 = 2; - RADIUS_BETWEEN_200_AND_300 = 3; - RADIUS_BETWEEN_300_AND_1000 = 4; - RADIUS_BETWEEN_1000_AND_10000 = 5; - RADIUS_LARGER_THAN_100000 = 6; - RADIUS_NEGATIVE = 7; -} - -// Caller Activity Importance. -enum ActivityImportance { - IMPORTANCE_UNKNOWN = 0; - IMPORTANCE_TOP = 1; - IMPORTANCE_FORGROUND_SERVICE = 2; - IMPORTANCE_BACKGROUND = 3; -} diff --git a/core/proto/android/stats/mediametrics/mediametrics.proto b/core/proto/android/stats/mediametrics/mediametrics.proto deleted file mode 100644 index eb8a3b19f263..000000000000 --- a/core/proto/android/stats/mediametrics/mediametrics.proto +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; - -package android.stats.mediametrics; - -/** - * Track how we arbitrate between microphone/input requests. - * Logged from - * frameworks/av/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp - * frameworks/av/services/mediaanalytics/statsd_audiopolicy.cpp - * Next Tag: 10 - */ -message AudioPolicyData { - optional int32 status = 1; - optional string request_source = 2; - optional string request_package = 3; - optional int32 request_session = 4; - optional string request_device = 5; - optional string active_source = 6; - optional string active_package = 7; - optional int32 active_session = 8; - optional string active_device = 9; -} - -/** - * Track properties of audio recording - * Logged from - * frameworks/av/media/libaudioclient/AudioRecord.cpp - * frameworks/av/services/mediaanalytics/statsd_audiorecord.cpp - * Next Tag: 16 - */ -message AudioRecordData { - optional string encoding = 1; - optional string source = 2; - optional int32 latency = 3; - optional int32 samplerate = 4; - optional int32 channels = 5; - optional int64 created_millis = 6; - optional int64 duration_millis = 7; - optional int32 count = 8; - optional int32 error_code = 9; - optional string error_function = 10; - optional int32 port_id = 11; - optional int32 frame_count = 12; - optional string attributes = 13; - optional int64 channel_mask = 14; - optional int64 start_count = 15; - -} - -/** - * Track audio thread performance data - * Logged from - * frameworks/av/media/libnblog/ReportPerformance.cpp - * frameworks/av/services/mediaanalytics/statsd_audiothread.cpp - * Next Tag: 28 - */ -message AudioThreadData { - optional string type = 1; - optional int32 framecount = 2; - optional int32 samplerate = 3; - optional string work_millis_hist = 4; - optional string latency_millis_hist = 5; - optional string warmup_millis_hist = 6; - optional int64 underruns = 7; - optional int64 overruns = 8; - optional int64 active_millis = 9; - optional int64 duration_millis = 10; - - optional int32 id = 11; - optional int32 port_id = 12; - optional int32 sample_rate = 13; - optional int64 channel_mask = 14; - optional string encoding = 15; - optional int32 frame_count = 16; - optional string output_device = 17; - optional string input_device = 18; - optional double io_jitter_mean_millis = 19; - optional double io_jitter_stddev_millis = 20; - optional double process_time_mean_millis = 21; - optional double process_time_stddev_millis = 22; - optional double timestamp_jitter_mean_millis = 23; - optional double timestamp_jitter_stddev_millis = 24; - optional double latency_mean_millis = 25; - optional double latency_stddev_millis = 26; - -} - -/** - * Track audio track playback data - * Logged from - * frameworks/av/media/libaudioclient/AudioTrack.cpp - * frameworks/av/services/mediaanalytics/statsd_audiotrack.cpp - * Next Tag: 12 - */ -message AudioTrackData { - optional string stream_type = 1; - optional string content_type = 2; - optional string track_usage = 3; - optional int32 sample_rate = 4; - optional int64 channel_mask = 5; - - optional int32 underrun_frames = 6; - optional int32 startup_glitch = 7; - - optional int32 port_id = 8; - optional string encoding = 9; - optional int32 frame_count = 10; - optional string attributes = 11; - - -} - -/** - * Track Media Codec usage - * Logged from: - * frameworks/av/media/libstagefright/MediaCodec.cpp - * frameworks/av/services/mediaanalytics/statsd_codec.cpp - * Next Tag: 26 - */ -message CodecData { - optional string codec = 1; - optional string mime = 2; - optional string mode = 3; - optional int32 encoder = 4; - optional int32 secure = 5; - optional int32 width = 6; - optional int32 height = 7; - optional int32 rotation = 8; - optional int32 crypto = 9; - optional int32 profile = 10; - optional int32 level = 11; - optional int32 max_width = 12; - optional int32 max_height = 13; - optional int32 error_code = 14; - optional string error_state = 15; - optional int64 latency_max = 16; - optional int64 latency_min = 17; - optional int64 latency_avg = 18; - optional int64 latency_count = 19; - optional int64 latency_unknown = 20; - optional int32 queue_input_buffer_error = 21; - optional int32 queue_secure_input_buffer_error = 22; - optional string bitrate_mode = 23; - optional int32 bitrate = 24; - optional int64 lifetime_millis = 25; -} - -/** - * Track Media Extractor (pulling video/audio streams out of containers) usage - * Logged from: - * frameworks/av/media/libstagefright/RemoteMediaExtractor.cpp - * frameworks/av/services/mediaanalytics/statsd_extractor.cpp - * Next Tag: 5 - */ -message ExtractorData { - optional string format = 1; - optional string mime = 2; - optional int32 tracks = 3; - - enum EntryPoint { - UNSET = 0; // For backwards compatibility with clients that don't - // collect the entry point. - SDK = 1; - NDK_WITH_JVM = 2; - NDK_NO_JVM = 3; - OTHER = 4; // For extractor users that don't make use of the APIs. - } - - optional EntryPoint entry_point = 4 [default = UNSET]; -} - -/** - * Track Media Player usage - * this handles both nuplayer and nuplayer2 - * Logged from: - * frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp - * frameworks/av/media/libmediaplayer2/nuplayer2/NuPlayer2Driver.cpp - * frameworks/av/services/mediaanalytics/statsd_nuplayer.cpp - * Next Tag: 21 - */ -message NuPlayerData { - optional string whichPlayer = 1; - - optional string video_mime = 2; - optional string video_codec = 3; - optional int32 width = 4; - optional int32 height = 5; - optional int64 frames = 6; - optional int64 frames_dropped = 7; - optional double framerate = 8; - optional string audio_mime = 9; - optional string audio_codec = 10; - optional int64 duration_millis = 11; - optional int64 playing_millis = 12; - optional int32 error = 13; - optional int32 error_code = 14; - optional string error_state = 15; - optional string data_source_type = 16; - optional int64 rebuffering_millis = 17; - optional int32 rebuffers = 18; - optional int32 rebuffer_at_exit = 19; - optional int64 frames_dropped_startup = 20; -} - -/** - * Track information about recordings (e.g. camcorder) - * Logged from - * frameworks/av/media/libmediaplayerservice/StagefrightRecorder.cpp - * frameworks/av/services/mediaanalytics/if_statsd.cpp - * Next Tag: 22 - */ -message RecorderData { - optional string audio_mime = 1; - optional string video_mime = 2; - optional int32 video_profile = 3; - optional int32 video_level = 4; - optional int32 width = 5; - optional int32 height = 6; - optional int32 rotation = 7; - optional int32 framerate = 8; - optional int32 capture_fps = 9; - optional double capture_fps_enable = 10; - optional int64 duration_millis = 11; - optional int64 paused_millis = 12; - optional int32 paused_count = 13; - optional int32 audio_bitrate = 14; - optional int32 audio_channels = 15; - optional int32 audio_samplerate = 16; - optional int32 movie_timescale = 17; - optional int32 audio_timescale = 18; - optional int32 video_timescale = 19; - optional int32 video_bitrate = 20; - optional int32 iframe_interval = 21; -} - -enum StreamType { - STREAM_TYPE_UNKNOWN = 0; - STREAM_TYPE_OTHER = 1; - STREAM_TYPE_PROGRESSIVE = 2; - STREAM_TYPE_DASH = 3; - STREAM_TYPE_HLS = 4; - STREAM_TYPE_SS = 5; -} - -enum DrmType { - DRM_TYPE_NONE = 0; - DRM_TYPE_OTHER = 1; - DRM_TYPE_PLAY_READY = 2; - DRM_TYPE_WV_L1 = 3; - DRM_TYPE_WV_L3 = 4; -} - -enum PlaybackType { - PLAYBACK_TYPE_VOD = 0; - PLAYBACK_TYPE_LIVE = 1; - PLAYBACK_TYPE_OTHER = 2; -} - -enum ContentType { - CONTENT_TYPE_MAIN = 0; - CONTENT_TYPE_AD = 1; - CONTENT_TYPE_OTHER = 2; -} - -enum StreamSourceType { - STREAM_SOURCE_UNKNOWN = 0; - STREAM_SOURCE_NETWORK = 1; - STREAM_SOURCE_DEVICE = 2; - STREAM_SOURCE_MIXED = 3; -} -enum NetworkType { - NETWORK_TYPE_NONE = 0; - NETWORK_TYPE_OTHER = 1; - NETWORK_TYPE_WIFI = 2; - NETWORK_TYPE_ETHERNET = 3; - NETWORK_TYPE_2G = 4; - NETWORK_TYPE_3G = 5; - NETWORK_TYPE_4G = 6; - NETWORK_TYPE_5G_NSA = 7; - NETWORK_TYPE_5G_SA = 8; -} - -enum PlaybackState { - // Playback has not started (initial state) - NOT_STARTED = 0; - // Playback is buffering in the background for initial playback start - JOINING_BACKGROUND = 1; - // Playback is buffering in the foreground for initial playback start - JOINING_FOREGROUND = 2; - // Playback is actively playing - PLAYING = 3; - // Playback is paused but ready to play - PAUSED = 4; - // Playback is handling a seek - SEEKING = 5; - // Playback is buffering to resume active playback - BUFFERING = 6; - // Playback is buffering while paused - PAUSED_BUFFERING = 7; - // Playback is suppressed (e.g. due to audio focus loss) - SUPPRESSED = 8; - // Playback is suppressed (e.g. due to audio focus loss) while buffering to resume a - // playback - SUPPRESSED_BUFFERING = 9; - // Playback has reached the end of the media - ENDED = 10; - // Playback is stopped and can be restarted - STOPPED = 11; - // Playback is stopped due a fatal error and can be retried - FAILED = 12; - // Playback is interrupted by an ad - INTERRUPTED_BY_AD = 13; - // Playback is abandoned before reaching the end of the media - ABANDONED = 14; -} - -enum PlaybackErrorCode { - ERROR_CODE_UNKNOWN = 0; - ERROR_CODE_OTHER = 1; - ERROR_CODE_RUNTIME = 2; -} - -enum TrackType { - AUDIO = 0; - VIDEO = 1; - TEXT = 2; -} -enum TrackState { - OFF = 0; - ON = 1; -} -enum TrackChangeReason { - REASON_UNKNOWN = 0; - REASON_OTHER = 1; - REASON_INITIAL = 2; - REASON_MANUAL = 3; - REASON_ADAPTIVE = 4; -} diff --git a/core/proto/android/stats/otaupdate/updateengine_enums.proto b/core/proto/android/stats/otaupdate/updateengine_enums.proto deleted file mode 100644 index a6e9919ba606..000000000000 --- a/core/proto/android/stats/otaupdate/updateengine_enums.proto +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; -package android.stats.otaupdate; - -// The payload type of an OTA update attempt on A/B devices. -enum PayloadType { - FULL = 10000; - DELTA = 10001; -} - -// The attempt result reported by the update engine for an OTA update. -enum AttemptResult { - UPDATE_SUCCEEDED = 10000; - INTERNAL_ERROR = 10001; - PAYLOAD_DOWNLOAD_ERROR = 10002; - METADATA_MALFORMED = 10003; - OPERATION_MALFORMED = 10004; - OPERATION_EXECUTION_ERROR = 10005; - METADATA_VERIFICATION_FAILED = 10006; - PAYLOAD_VERIFICATION_FAILED = 10007; - VERIFICATION_FAILED = 10008; - POSTINSTALL_FAILED = 10009; - ABNORMAL_TERMINATION = 10010; - UPDATE_CANCELED = 10011; - UPDATE_SUCCEEDED_NOT_ACTIVE = 10012; -} - -// The error code reported by the update engine after an OTA update attempt -// on A/B devices. More details in system/update_engine/common/error_code.h -enum ErrorCode { - SUCCESS = 10000; - ERROR = 10001; - FILESYSTEM_COPIER_ERROR = 10004; - POST_INSTALL_RUNNER_ERROR = 10005; - PAYLOAD_MISMATCHED_TYPE_ERROR = 10006; - INSTALL_DEVICE_OPEN_ERROR = 10007; - KERNEL_DEVICE_OPEN_ERROR = 10008; - DOWNLOAD_TRANSFER_ERROR = 10009; - PAYLOAD_HASH_MISMATCH_ERROR = 10010; - PAYLOAD_SIZE_MISMATCH_ERROR = 10011; - DOWNLOAD_PAYLOAD_VERIFICATION_ERROR = 10012; - DOWNLOAD_NEW_PARTITION_INFO_ERROR = 10013; - DOWNLOAD_WRITE_ERROR = 10014; - NEW_ROOTFS_VERIFICATION_ERROR = 10015; - SIGNED_DELTA_PAYLOAD_EXPECTED_ERROR = 10017; - DOWNLOAD_PAYLOAD_PUB_KEY_VERIFICATION_ERROR = 10018; - DOWNLOAD_STATE_INITIALIZATION_ERROR = 10020; - DOWNLOAD_INVALID_METADATA_MAGIC_STRING = 10021; - DOWNLOAD_SIGNATURE_MISSING_IN_MANIFEST = 10022; - DOWNLOAD_MANIFEST_PARSE_ERROR = 10023; - DOWNLOAD_METADATA_SIGNATURE_ERROR = 10024; - DOWNLOAD_METADATA_SIGNATURE_VERIFICATION_ERROR = 10025; - DOWNLOAD_METADATA_SIGNATURE_MISMATCH = 10026; - DOWNLOAD_OPERATION_HASH_VERIFICATION_ERROR = 10027; - DOWNLOAD_OPERATION_EXECUTION_ERROR = 10028; - DOWNLOAD_OPERATION_HASH_MISMATCH = 10029; - DOWNLOAD_INVALID_METADATA_SIZE = 10032; - DOWNLOAD_INVALID_METADATA_SIGNATURE = 10033; - DOWNLOAD_OPERATION_HASH_MISSING_ERROR = 10038; - DOWNLOAD_METADATA_SIGNATURE_MISSING_ERROR = 10039; - UNSUPPORTED_MAJOR_PAYLOAD_VERSION = 10044; - UNSUPPORTED_MINOR_PAYLOAD_VERSION = 10045; - FILESYSTEM_VERIFIER_ERROR = 10047; - USER_CANCELED = 10048; - PAYLOAD_TIMESTAMP_ERROR = 10051; - UPDATED_BUT_NOT_ACTIVE = 10052; -} diff --git a/core/proto/android/stats/style/Android.bp b/core/proto/android/stats/style/Android.bp deleted file mode 100644 index f085a52f8cdb..000000000000 --- a/core/proto/android/stats/style/Android.bp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library { - name: "styleprotosnano", - proto: { - type: "nano", - output_params: ["store_unknown_fields=true"], - include_dirs: ["external/protobuf/src"], - }, - - sdk_version: "current", - srcs: [ - "*.proto", - ], -} diff --git a/core/proto/android/stats/style/style_enums.proto b/core/proto/android/stats/style/style_enums.proto deleted file mode 100644 index 2876882e78ba..000000000000 --- a/core/proto/android/stats/style/style_enums.proto +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; -package android.stats.style; -option java_multiple_files = true; - -enum Action { - DEFAULT_ACTION = 0; - ONRESUME = 1; - ONSTOP = 2; - PICKER_SELECT = 3; - PICKER_APPLIED = 4; - WALLPAPER_OPEN_CATEGORY = 5; - WALLPAPER_SELECT = 6; - WALLPAPER_APPLIED = 7; - WALLPAPER_EXPLORE = 8; - WALLPAPER_DOWNLOAD = 9; - WALLPAPER_REMOVE = 10; - LIVE_WALLPAPER_DOWNLOAD_SUCCESS = 11; - LIVE_WALLPAPER_DOWNLOAD_FAILED = 12; - LIVE_WALLPAPER_DOWNLOAD_CANCELLED = 13; - LIVE_WALLPAPER_DELETE_SUCCESS = 14; - LIVE_WALLPAPER_DELETE_FAILED = 15; - LIVE_WALLPAPER_APPLIED = 16; - LIVE_WALLPAPER_INFO_SELECT = 17; - LIVE_WALLPAPER_CUSTOMIZE_SELECT = 18; - LIVE_WALLPAPER_QUESTIONNAIRE_SELECT = 19; - LIVE_WALLPAPER_QUESTIONNAIRE_APPLIED = 20; - LIVE_WALLPAPER_EFFECT_SHOW = 21; - APP_LAUNCHED = 22; -} - -enum LocationPreference { - LOCATION_PREFERENCE_UNSPECIFIED = 0; - LOCATION_UNAVAILABLE = 1; - LOCATION_CURRENT = 2; - LOCATION_MANUAL = 3; -} - -enum DatePreference { - DATE_PREFERENCE_UNSPECIFIED = 0; - DATE_UNAVAILABLE = 1; - DATE_MANUAL = 2; -} - -enum LaunchedPreference { - LAUNCHED_PREFERENCE_UNSPECIFIED = 0; - LAUNCHED_LAUNCHER = 1; - LAUNCHED_SETTINGS = 2; - LAUNCHED_SUW = 3; - LAUNCHED_TIPS = 4; - LAUNCHED_LAUNCH_ICON = 5; - LAUNCHED_CROP_AND_SET_ACTION = 6; - LAUNCHED_DEEP_LINK = 7; -} diff --git a/core/proto/android/stats/sysui/notification_enums.proto b/core/proto/android/stats/sysui/notification_enums.proto deleted file mode 100644 index 30bdecae07d1..000000000000 --- a/core/proto/android/stats/sysui/notification_enums.proto +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.stats.sysui; - -// Enum used in NotificationReported and NotificationChannelModified atoms -enum NotificationImportance { // Constants from NotificationManager.java - IMPORTANCE_UNSPECIFIED = -1000; // Should not occur for real notifications. - IMPORTANCE_NONE = 0; // No importance: does not show in the shade. - IMPORTANCE_MIN = 1; // Minimum to show in the shade. - IMPORTANCE_LOW = 2; // Shows in shade, maybe status bar, no buzz/beep. - IMPORTANCE_DEFAULT = 3; // Shows everywhere, makes noise, no heads-up. - IMPORTANCE_HIGH = 4; // Shows everywhere, makes noise, heads-up, may full-screen. - IMPORTANCE_IMPORTANT_CONVERSATION = 5; // High + isImportantConversation(). -} diff --git a/core/proto/android/stats/textclassifier/Android.bp b/core/proto/android/stats/textclassifier/Android.bp deleted file mode 100644 index bf9022711206..000000000000 --- a/core/proto/android/stats/textclassifier/Android.bp +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -java_library_static { - name: "textclassifierprotoslite", - proto: { - type: "lite", - }, - srcs: [ - "*.proto", - ], -}
\ No newline at end of file diff --git a/core/proto/android/stats/textclassifier/textclassifier_enums.proto b/core/proto/android/stats/textclassifier/textclassifier_enums.proto deleted file mode 100644 index 4be7b7c2df7c..000000000000 --- a/core/proto/android/stats/textclassifier/textclassifier_enums.proto +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open 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. - */ - -syntax = "proto2"; -package android.stats.textclassifier; -option java_multiple_files = true; - -enum EventType { - TYPE_UNKNOWN = 0; - // User started a new selection. - SELECTION_STARTED = 1; - // User modified an existing selection. - SELECTION_MODIFIED = 2; - // Smart selection triggered for a single token (word). - SMART_SELECTION_SINGLE = 3; - // Smart selection triggered spanning multiple tokens (words). - SMART_SELECTION_MULTI = 4; - // Something else other than user or the default TextClassifier triggered a selection. - AUTO_SELECTION = 5; - // Smart actions shown to the user. - ACTIONS_SHOWN = 6; - // User clicked a link. - LINK_CLICKED = 7; - // User typed over the selection. - OVERTYPE = 8; - // User clicked on Copy action. - COPY_ACTION = 9; - // User clicked on Paste action. - PASTE_ACTION = 10; - // User clicked on Cut action. - CUT_ACTION = 11; - // User clicked on Share action. - SHARE_ACTION = 12; - // User clicked on a Smart action. - SMART_ACTION = 13; - // User dragged+dropped the selection. - SELECTION_DRAG = 14; - // Selection is destroyed. - SELECTION_DESTROYED = 15; - // User clicked on a custom action. - OTHER_ACTION = 16; - // User clicked on Select All action - SELECT_ALL = 17; - // User reset the smart selection. - SELECTION_RESET = 18; - // User composed a reply. - MANUAL_REPLY = 19; - // TextClassifier generated some actions - ACTIONS_GENERATED = 20; - // Some text links were generated - LINKS_GENERATED = 21; -} - -enum WidgetType { - WIDGET_TYPE_UNKNOWN = 0; - // Standard TextView - WIDGET_TYPE_TEXTVIEW = 1; - // EditText - WIDGET_TYPE_EDITTEXT = 2; - // Not selectable textview - WIDGET_TYPE_UNSELECTABLE_TEXTVIEW = 3; - // Standard Webview - WIDGET_TYPE_WEBVIEW = 4; - // Editable TextView - WIDGET_TYPE_EDIT_WEBVIEW = 5; - // Custom text widget - WIDGET_TYPE_CUSTOM_TEXTVIEW = 6; - // Custom editable text widget. - WIDGET_TYPE_CUSTOM_EDITTEXT = 7; - // Non-selectable text widget. - WIDGET_TYPE_CUSTOM_UNSELECTABLE_TEXTVIEW = 8; - // Notification - WIDGET_TYPE_NOTIFICATION = 9; -} diff --git a/core/proto/android/stats/tls/enums.proto b/core/proto/android/stats/tls/enums.proto deleted file mode 100644 index a64137d7caa9..000000000000 --- a/core/proto/android/stats/tls/enums.proto +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -syntax = "proto2"; -package android.stats.tls; - -// Keep in sync with -// external/conscrypt/{android,platform}/src/main/java/org/conscrypt/Platform.java -enum Protocol { - UNKNOWN_PROTO = 0; - SSL_V3 = 1; - TLS_V1 = 2; - TLS_V1_1 = 3; - TLS_V1_2 = 4; - TLS_V1_3 = 5; -} - -// Cipher suites' ids are based on IANA's database: -// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4 -// -// If you add new cipher suite, make sure id is the same as in IANA's database (see link above) -// -// Keep in sync with -// external/conscrypt/{android,platform}/src/main/java/org/conscrypt/Platform.java -enum CipherSuite { - UNKNOWN_CIPHER_SUITE = 0x0000; - - TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A; - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014; - TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035; - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009; - TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013; - TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F; - TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A; - - // TLSv1.2 cipher suites - TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C; - TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D; - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F; - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030; - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B; - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C; - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9; - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8; - - // Pre-Shared Key (PSK) cipher suites - TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C; - TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D; - TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035; - TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036; - TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAC; - - // TLS 1.3 cipher suites - TLS_AES_128_GCM_SHA256 = 0x1301; - TLS_AES_256_GCM_SHA384 = 0x1302; - TLS_CHACHA20_POLY1305_SHA256 = 0x1303; -} - diff --git a/core/proto/android/stats/tv/tif_enums.proto b/core/proto/android/stats/tv/tif_enums.proto deleted file mode 100644 index a9028e529186..000000000000 --- a/core/proto/android/stats/tv/tif_enums.proto +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -package android.stats.tv; -option java_multiple_files = true; - -// Enums for TV Input Framework -option java_outer_classname = "TifStatsEnums"; - -// Tune State of a TV Input Service Framework -enum TifTuneState { - TIF_TUNE_STATE_UNKNOWN = 0; - CREATED = 1; - SURFACE_ATTACHED = 2; - SURFACE_DETACHED = 3; - RELEASED = 4; - TUNE_STARTED = 5; - VIDEO_AVAILABLE = 6; - - // Keep in sync with TvInputManager - // Use the TvInputManager value + 100 - VIDEO_UNAVAILABLE_REASON_UNKNOWN = 100; - VIDEO_UNAVAILABLE_REASON_TUNING = 101; - VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 102; - VIDEO_UNAVAILABLE_REASON_BUFFERING = 103; - VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY = 104; - VIDEO_UNAVAILABLE_REASON_NOT_CONNECTED = 105; - VIDEO_UNAVAILABLE_REASON_INSUFFICIENT_RESOURCE = 106; - VIDEO_UNAVAILABLE_REASON_CAS_INSUFFICIENT_OUTPUT_PROTECTION=107; - VIDEO_UNAVAILABLE_REASON_CAS_PVR_RECORDING_NOT_ALLOWED=108; - VIDEO_UNAVAILABLE_REASON_CAS_NO_LICENSE=109; - VIDEO_UNAVAILABLE_REASON_CAS_LICENSE_EXPIRED=110; - VIDEO_UNAVAILABLE_REASON_CAS_NEED_ACTIVATION=111; - VIDEO_UNAVAILABLE_REASON_CAS_NEED_PAIRING=112; - VIDEO_UNAVAILABLE_REASON_CAS_NO_CARD=113; - VIDEO_UNAVAILABLE_REASON_CAS_CARD_MUTE=114; - VIDEO_UNAVAILABLE_REASON_CAS_CARD_INVALID=115; - VIDEO_UNAVAILABLE_REASON_CAS_BLACKOUT=116; - VIDEO_UNAVAILABLE_REASON_CAS_REBOOTING=117; - VIDEO_UNAVAILABLE_REASON_CAS_UNKNOWN=118; -} diff --git a/core/proto/android/telecomm/enums.proto b/core/proto/android/telecomm/enums.proto deleted file mode 100644 index 5ca4a85f7c6a..000000000000 --- a/core/proto/android/telecomm/enums.proto +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.telecom; - -option java_outer_classname = "TelecomProtoEnums"; -option java_multiple_files = true; - -/** - * Call states, primarily used in CallState.java, - * Call.java, and CallsManager.java in packages/services. - */ -enum CallStateEnum { - /** - * Indicates that a call is new and not connected. This is used as the default state internally - * within Telecom and should not be used between Telecom and call services. Call services are - * not expected to ever interact with NEW calls, but {@link android.telecom.InCallService}s will - * see calls in this state. - */ - NEW = 0; - - /** - * The initial state of an outgoing {@code Call}. - * Common transitions are to {@link #DIALING} state for a successful call or - * {@link #DISCONNECTED} if it failed. - */ - CONNECTING = 1; - - /** - * The state of an outgoing {@code Call} when waiting on user to select a - * {@link android.telecom.PhoneAccount} through which to place the call. - */ - SELECT_PHONE_ACCOUNT = 2; - - /** - * Indicates that a call is outgoing and in the dialing state. A call transitions to this state - * once an outgoing call has begun (e.g., user presses the dial button in Dialer). Calls in this - * state usually transition to {@link #ACTIVE} if the call was answered or {@link #DISCONNECTED} - * if the call was disconnected somehow (e.g., failure or cancellation of the call by the user). - */ - DIALING = 3; - - /** - * Indicates that a call is incoming and the user still has the option of answering, rejecting, - * or doing nothing with the call. This state is usually associated with some type of audible - * ringtone. Normal transitions are to {@link #ACTIVE} if answered or {@link #DISCONNECTED} - * otherwise. - */ - RINGING = 4; - - /** - * Indicates that a call is currently connected to another party and a communication channel is - * open between them. The normal transition to this state is by the user answering a - * {@link #DIALING} call or a {@link #RINGING} call being answered by the other party. - */ - ACTIVE = 5; - - /** - * Indicates that the call is currently on hold. In this state, the call is not terminated - * but no communication is allowed until the call is no longer on hold. The typical transition - * to this state is by the user putting an {@link #ACTIVE} call on hold by explicitly performing - * an action, such as clicking the hold button. - */ - ON_HOLD = 6; - - /** - * Indicates that a call is currently disconnected. All states can transition to this state - * by the call service giving notice that the connection has been severed. When the user - * explicitly ends a call, it will not transition to this state until the call service confirms - * the disconnection or communication was lost to the call service currently responsible for - * this call (e.g., call service crashes). - */ - DISCONNECTED = 7; - - /** - * Indicates that the call was attempted (mostly in the context of outgoing, at least at the - * time of writing) but cancelled before it was successfully connected. - */ - ABORTED = 8; - - /** - * Indicates that the call is in the process of being disconnected and will transition next - * to a {@link #DISCONNECTED} state. - * <p> - * This state is not expected to be communicated from the Telephony layer, but will be reported - * to the InCall UI for calls where disconnection has been initiated by the user but the - * ConnectionService has confirmed the call as disconnected. - */ - DISCONNECTING = 9; - - /** - * Indicates that the call is in the process of being pulled to the local device. - * <p> - * This state should only be set on a call with - * {@link android.telecom.Connection#PROPERTY_IS_EXTERNAL_CALL} and - * {@link android.telecom.Connection#CAPABILITY_CAN_PULL_CALL}. - */ - PULLING = 10; - - /** - * Indicates that an incoming call has been answered by the in-call UI, but Telephony hasn't yet - * set the call to active. - */ - ANSWERED = 11; - - /** - * Indicates that the call is undergoing audio processing by a different app in the background. - * @see android.telecom.Call#STATE_AUDIO_PROCESSING - */ - AUDIO_PROCESSING = 12; - - /** - * Indicates that the call is in a fake ringing state. - * @see android.telecom.Call#STATE_SIMULATED_RINGING - */ - SIMULATED_RINGING = 13; -} - -// Disconnect causes for a call. Primarily used by android/telecom/DisconnectCause.java -enum DisconnectCauseEnum { - /** - * Disconnected because of an unknown or unspecified reason. - */ - UNKNOWN = 0; - - /** - * Disconnected because there was an error, such as a problem with the network. - */ - ERROR = 1; - - /** - * Disconnected because of a local user-initiated action, such as hanging up. - */ - LOCAL = 2; - - /** - * Disconnected because of a remote user-initiated action, such as the other party hanging up - * up. - */ - REMOTE = 3; - - /** - * Disconnected because it has been canceled. - */ - CANCELED = 4; - - /** - * Disconnected because there was no response to an incoming call. - */ - MISSED = 5; - - /** - * Disconnected because the user rejected an incoming call. - */ - REJECTED = 6; - - /** - * Disconnected because the other party was busy. - */ - BUSY = 7; - - /** - * Disconnected because of a restriction on placing the call, such as dialing in airplane - * mode. - */ - RESTRICTED = 8; - - /** - * Disconnected for reason not described by other disconnect codes. - */ - OTHER = 9; - - /** - * Disconnected because the connection manager did not support the call. The call will be tried - * again without a connection manager. See {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER}. - */ - CONNECTION_MANAGER_NOT_SUPPORTED = 10; - - /** - * Disconnected because the user did not locally answer the incoming call, but it was answered - * on another device where the call was ringing. - */ - ANSWERED_ELSEWHERE = 11; - - /** - * Disconnected because the call was pulled from the current device to another device. - */ - CALL_PULLED = 12; -} diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto deleted file mode 100644 index b435fe7d9784..000000000000 --- a/core/proto/android/telephony/enums.proto +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.telephony; - -option java_outer_classname = "TelephonyProtoEnums"; -option java_multiple_files = true; - -enum CallBearerEnum { - /** Call bearer is unknown or invalid */ - CALL_BEARER_UNKNOWN = 0; - - /** Call bearer is legacy CS */ - CALL_BEARER_CS = 1; - - /** Call bearer is IMS */ - CALL_BEARER_IMS = 2; -} - -enum CallDirectionEnum { - /** Call direction: unknown or invalid */ - CALL_DIRECTION_UNKNOWN = 0; - - /** Call direction: mobile originated (outgoing for this device) */ - CALL_DIRECTION_MO = 1; - - /** Call direction: mobile terminated (incoming for this device) */ - CALL_DIRECTION_MT = 2; -} - -// Call setup duration buckets. -// See com.android.internal.telephony.metrics.VoiceCallSessionStats for definition. -enum CallSetupDurationEnum { - CALL_SETUP_DURATION_UNKNOWN = 0; - CALL_SETUP_DURATION_EXTREMELY_FAST = 1; - CALL_SETUP_DURATION_ULTRA_FAST = 2; - CALL_SETUP_DURATION_VERY_FAST = 3; - CALL_SETUP_DURATION_FAST = 4; - CALL_SETUP_DURATION_NORMAL = 5; - CALL_SETUP_DURATION_SLOW = 6; - CALL_SETUP_DURATION_VERY_SLOW = 7; - CALL_SETUP_DURATION_ULTRA_SLOW = 8; - CALL_SETUP_DURATION_EXTREMELY_SLOW = 9; -} - -// Data conn. power states, primarily used by android/telephony/DataConnectionRealTimeInfo.java. -enum DataConnectionPowerStateEnum { - DATA_CONNECTION_POWER_STATE_LOW = 1; - DATA_CONNECTION_POWER_STATE_MEDIUM = 2; - DATA_CONNECTION_POWER_STATE_HIGH = 3; - DATA_CONNECTION_POWER_STATE_UNKNOWN = 2147483647; // Java Integer.MAX_VALUE; -} - -// Network type enums, primarily used by android/telephony/TelephonyManager.java. -// Do not add negative types. -enum NetworkTypeEnum { - NETWORK_TYPE_UNKNOWN = 0; - NETWORK_TYPE_GPRS = 1; - NETWORK_TYPE_EDGE = 2; - NETWORK_TYPE_UMTS = 3; - NETWORK_TYPE_CDMA = 4; - NETWORK_TYPE_EVDO_0 = 5; - NETWORK_TYPE_EVDO_A = 6; - NETWORK_TYPE_1XRTT = 7; - NETWORK_TYPE_HSDPA = 8; - NETWORK_TYPE_HSUPA = 9; - NETWORK_TYPE_HSPA = 10; - NETWORK_TYPE_IDEN = 11; - NETWORK_TYPE_EVDO_B = 12; - NETWORK_TYPE_LTE = 13; - NETWORK_TYPE_EHRPD = 14; - NETWORK_TYPE_HSPAP = 15; - NETWORK_TYPE_GSM = 16; - NETWORK_TYPE_TD_SCDMA = 17; - NETWORK_TYPE_IWLAN = 18; - NETWORK_TYPE_LTE_CA = 19; - NETWORK_TYPE_NR = 20; -} - -// Roaming type enums, see android.telephony.ServiceState.RoamingType for definitions. -enum RoamingTypeEnum { - ROAMING_TYPE_NOT_ROAMING = 0; - ROAMING_TYPE_ROAMING = 1; - ROAMING_TYPE_ROAMING_DOMESTIC = 2; - ROAMING_TYPE_ROAMING_INTERNATIONAL = 3; -} - -// Signal strength levels, as defined in android/telephony/SignalStrength.java. -enum SignalStrengthEnum { - SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0; - SIGNAL_STRENGTH_POOR = 1; - SIGNAL_STRENGTH_MODERATE = 2; - SIGNAL_STRENGTH_GOOD = 3; - SIGNAL_STRENGTH_GREAT = 4; -} - -enum ServiceStateEnum { - /** - * Normal operation condition, the phone is registered - * with an operator either in home network or in roaming. - */ - SERVICE_STATE_IN_SERVICE = 0; - - /** - * Phone is not registered with any operator, the phone - * can be currently searching a new operator to register to, or not - * searching to registration at all, or registration is denied, or radio - * signal is not available. - */ - SERVICE_STATE_OUT_OF_SERVICE = 1; - - /** - * The phone is registered and locked. Only emergency numbers are allowed. {@more} - */ - SERVICE_STATE_EMERGENCY_ONLY = 2; - - /** - * Radio of telephony is explicitly powered off. - */ - SERVICE_STATE_POWER_OFF = 3; -} - -enum SimStateEnum { - SIM_STATE_UNKNOWN = 0; - /** SIM card state: no SIM card is available in the device */ - SIM_STATE_ABSENT = 1; - /** SIM card state: Locked: requires the user's SIM PIN to unlock */ - SIM_STATE_PIN_REQUIRED = 2; - /** SIM card state: Locked: requires the user's SIM PUK to unlock */ - SIM_STATE_PUK_REQUIRED = 3; - /** SIM card state: Locked: requires a network PIN to unlock */ - SIM_STATE_NETWORK_LOCKED = 4; - /** SIM card state: Ready */ - SIM_STATE_READY = 5; - /** SIM card state: SIM Card is NOT READY */ - SIM_STATE_NOT_READY = 6; - /** SIM card state: SIM Card Error, permanently disabled */ - SIM_STATE_PERM_DISABLED = 7; - /** SIM card state: SIM Card Error, present but faulty */ - SIM_STATE_CARD_IO_ERROR = 8; - /** SIM card state: SIM Card restricted, present but not usable due to - * carrier restrictions. - */ - SIM_STATE_CARD_RESTRICTED = 9; - /** - * SIM card state: Loaded: SIM card applications have been loaded - * @hide - */ - SIM_STATE_LOADED = 10; - /** - * SIM card state: SIM Card is present - * @hide - */ - SIM_STATE_PRESENT = 11; -} - -// Format of SMS message -enum SmsFormatEnum { - /** Unknown format */ - SMS_FORMAT_UNKNOWN = 0; - /** Format compliant with 3GPP TS 23.040 */ - SMS_FORMAT_3GPP = 1; - /** Format compliant with 3GPP2 TS C.S0015-B */ - SMS_FORMAT_3GPP2 = 2; -} - -// Technology used to carry an SMS message -enum SmsTechEnum { - /** - * Unknown SMS technology used to carry the SMS. - * This value is also used for injected SMS. - */ - SMS_TECH_UNKNOWN = 0; - /** The SMS was carried over CS bearer in 3GPP network */ - SMS_TECH_CS_3GPP = 1; - /** The SMS was carried over CS bearer in 3GPP2 network */ - SMS_TECH_CS_3GPP2 = 2; - /** The SMS was carried over IMS */ - SMS_TECH_IMS = 3; -} - -// Types of SMS message -enum SmsTypeEnum { - /** Normal type. */ - SMS_TYPE_NORMAL = 0; - /** SMS-PP (point-to-point). */ - SMS_TYPE_SMS_PP = 1; - /** Voicemail indication. */ - SMS_TYPE_VOICEMAIL_INDICATION = 2; - /** Type 0 message (3GPP TS 23.040 9.2.3.9). */ - SMS_TYPE_ZERO = 3; - /** WAP-PUSH message. */ - SMS_TYPE_WAP_PUSH = 4; -} - -// Incoming SMS errors -enum SmsIncomingErrorEnum { - SMS_SUCCESS = 0; - SMS_ERROR_GENERIC = 1; - SMS_ERROR_NO_MEMORY = 2; - SMS_ERROR_NOT_SUPPORTED = 3; -} - -// Outgoing SMS results -enum SmsSendResultEnum { - // Unknown error - SMS_SEND_RESULT_UNKNOWN = 0; - // Success - SMS_SEND_RESULT_SUCCESS = 1; - // Permanent error - SMS_SEND_RESULT_ERROR = 2; - // Temporary error, retry - SMS_SEND_RESULT_ERROR_RETRY = 3; - // Error over IMS, retry on CS - SMS_SEND_RESULT_ERROR_FALLBACK = 4; -} - -// Data profile of the data call. From -// frameworks/base/telephony/java/com/android/internal/telephony/RILConstants.java -enum DataProfileEnum { - DATA_PROFILE_DEFAULT = 0; - DATA_PROFILE_TETHERED = 1; - DATA_PROFILE_IMS = 2; - DATA_PROFILE_FOTA = 3; - DATA_PROFILE_CBS = 4; - DATA_PROFILE_OEM_BASE = 1000; - DATA_PROFILE_INVALID = -1; -} - -// Reason of data call deactivation. From -// frameworks/base/telephony/java/android/telephony/data/DataService.java#DeactivateDataReason -enum DataDeactivateReasonEnum { - DEACTIVATE_REASON_UNKNOWN = 0; - DEACTIVATE_REASON_NORMAL = 1; - DEACTIVATE_REASON_RADIO_OFF = 2; - DEACTIVATE_REASON_HANDOVER = 3; -} - -// IP type of the data call -// see frameworks/base/telephony/java/android/telephony/data/ApnSetting.java#ProtocolType -enum ApnProtocolEnum { - APN_PROTOCOL_IPV4 = 0; - APN_PROTOCOL_IPV6 = 1; - APN_PROTOCOL_IPV4V6 = 2; - APN_PROTOCOL_PPP = 3; -} - -// Action taken to recover a data call that is stalled. From -// frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/DcTracker.java -// #RecoveryAction -enum DataStallRecoveryActionEnum { - RECOVERY_ACTION_GET_DATA_CALL_LIST = 0; - RECOVERY_ACTION_CLEANUP = 1; - RECOVERY_ACTION_REREGISTER = 2; - RECOVERY_ACTION_RADIO_RESTART = 3; -} - -// Codec quality -enum CodecQuality { - /** Codec quality: unknown */ - CODEC_QUALITY_UNKNOWN = 0; - - /** Codec quality: narrowband */ - CODEC_QUALITY_NARROWBAND = 1; - - /** Codec quality: wideband */ - CODEC_QUALITY_WIDEBAND = 2; - - /** Codec quality: super-wideband */ - CODEC_QUALITY_SUPER_WIDEBAND = 3; - - /** Codec quality: fullband */ - CODEC_QUALITY_FULLBAND = 4; -} diff --git a/core/proto/android/view/enums.proto b/core/proto/android/view/enums.proto deleted file mode 100644 index a601abee17f6..000000000000 --- a/core/proto/android/view/enums.proto +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.view; - -option java_outer_classname = "ViewProtoEnums"; -option java_multiple_files = true; - -// Screen states, primarily used by android/view/Display.java. -enum DisplayStateEnum { - // The display state is unknown. - DISPLAY_STATE_UNKNOWN = 0; - // The display state is off. - DISPLAY_STATE_OFF = 1; - // The display state is on. - DISPLAY_STATE_ON = 2; - // The display is dozing in a low power state; it is still on but is - // optimized for showing system-provided content while the device is - // non-interactive. - DISPLAY_STATE_DOZE = 3; - // The display is dozing in a suspended low power state; it is still on - // but is optimized for showing static system-provided content while the - // device is non-interactive. - DISPLAY_STATE_DOZE_SUSPEND = 4; - // The display is on and optimized for VR mode. - DISPLAY_STATE_VR = 5; - // The display is in a suspended full power state; it is still on but the - // CPU is not updating it. - DISPLAY_STATE_ON_SUSPEND = 6; -} - -// Constants found in android.view.WindowManager. -enum TransitionTypeEnum { - TRANSIT_NONE = 0; - TRANSIT_UNSET = -1; - TRANSIT_ACTIVITY_OPEN = 6; - TRANSIT_ACTIVITY_CLOSE = 7; - TRANSIT_TASK_OPEN = 8; - TRANSIT_TASK_CLOSE = 9; - TRANSIT_TASK_TO_FRONT = 10; - TRANSIT_TASK_TO_BACK = 11; - TRANSIT_WALLPAPER_CLOSE = 12; - TRANSIT_WALLPAPER_OPEN = 13; - TRANSIT_WALLPAPER_INTRA_OPEN = 14; - TRANSIT_WALLPAPER_INTRA_CLOSE = 15; - TRANSIT_TASK_OPEN_BEHIND = 16; - TRANSIT_TASK_IN_PLACE = 17; - TRANSIT_ACTIVITY_RELAUNCH = 18; - TRANSIT_DOCK_TASK_FROM_RECENTS = 19 [deprecated=true]; - TRANSIT_KEYGUARD_GOING_AWAY = 20; - TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21; - TRANSIT_KEYGUARD_OCCLUDE = 22; - TRANSIT_KEYGUARD_UNOCCLUDE = 23; - TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 24; - TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 25; - TRANSIT_CRASHING_ACTIVITY_CLOSE = 26; -} diff --git a/core/proto/android/bluetooth/a2dp/enums.proto b/core/proto/android/view/inputmethod/inputconnection.proto index 5a025bdd6c10..ad9a95aa95e6 100644 --- a/core/proto/android/bluetooth/a2dp/enums.proto +++ b/core/proto/android/view/inputmethod/inputconnection.proto @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,21 +15,20 @@ */ syntax = "proto2"; -package android.bluetooth.a2dp; -option java_outer_classname = "BluetoothA2dpProtoEnums"; -option java_multiple_files = true; +import "frameworks/base/core/proto/android/privacy.proto"; + +package android.view.inputmethod; -// A2dp playback state enum, defined from: -// frameworks/base/core/java/android/bluetooth/BluetoothA2dp.java -enum PlaybackStateEnum { - PLAYBACK_STATE_UNKNOWN = 0; - PLAYBACK_STATE_PLAYING = 10; - PLAYBACK_STATE_NOT_PLAYING = 11; -} +option java_multiple_files = true; -enum AudioCodingModeEnum { - AUDIO_CODING_MODE_UNKNOWN = 0; - AUDIO_CODING_MODE_HARDWARE = 1; - AUDIO_CODING_MODE_SOFTWARE = 2; -} +/** + * Represents a {@link android.view.inputmethod.InputConnection} object. + */ +message InputConnectionProto { + optional string editable_text = 1 [(.android.privacy).dest = DEST_LOCAL]; + optional string selected_text = 2 [(.android.privacy).dest = DEST_LOCAL]; + optional int32 selected_text_start = 3; + optional int32 selected_text_end = 4; + optional int32 cursor_caps_mode = 5; +}
\ No newline at end of file diff --git a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto index 5c0f341cb9e4..c1dce6f2d093 100644 --- a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto +++ b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto @@ -24,6 +24,7 @@ import "frameworks/base/core/proto/android/view/viewrootimpl.proto"; import "frameworks/base/core/proto/android/view/insetscontroller.proto"; import "frameworks/base/core/proto/android/view/imeinsetssourceconsumer.proto"; import "frameworks/base/core/proto/android/view/inputmethod/editorinfo.proto"; +import "frameworks/base/core/proto/android/view/inputmethod/inputconnection.proto"; import "frameworks/base/core/proto/android/view/imefocuscontroller.proto"; import "frameworks/base/core/proto/android/server/inputmethod/inputmethodmanagerservice.proto"; @@ -70,6 +71,7 @@ message InputMethodClientsTraceProto { optional ImeInsetsSourceConsumerProto ime_insets_source_consumer = 5; optional EditorInfoProto editor_info = 6; optional ImeFocusControllerProto ime_focus_controller = 7; + optional InputConnectionProto input_connection = 8; } } diff --git a/core/proto/android/wifi/enums.proto b/core/proto/android/wifi/enums.proto deleted file mode 100644 index e676fef8c2e0..000000000000 --- a/core/proto/android/wifi/enums.proto +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; -package android.net.wifi; - -option java_outer_classname = "WifiProtoEnums"; -option java_multiple_files = true; - -/** - * Wifi Lock modes, primarily used in - * frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiLockManager.java. - */ -enum WifiModeEnum { - /** - * Deprecated. - * Wi-Fi will be kept active, and will behave normally. - */ - WIFI_MODE_FULL = 1 [deprecated=true]; - - /** - * Deprecated. - * Wi-Fi will be kept active, but the only operation that will be supported is initiation of - * scans, and the subsequent reporting of scan results. - */ - WIFI_MODE_SCAN_ONLY = 2 [deprecated=true]; - - /** - * Wi-Fi will not go to power save. - */ - WIFI_MODE_FULL_HIGH_PERF = 3; - - /** - * Wi-Fi will operate with a priority to achieve low latency. - */ - WIFI_MODE_FULL_LOW_LATENCY = 4; -} - -/** - * Wifi authentication type. - */ -enum WifiAuthType { - AUTH_TYPE_NONE = 0; - - // WPA pre-shared key. - AUTH_TYPE_WPA_PSK = 1; - // WPA using EAP authentication. Generally used with an external authentication server. - AUTH_TYPE_WPA_EAP = 2; - // IEEE 802.1X using EAP authentication and (optionally) dynamically generated WEP keys. - AUTH_TYPE_IEEE8021X = 3; - // WPA2 pre-shared key for use with soft access point. - AUTH_TYPE_WPA2_PSK = 4; - // Hotspot 2.0 r2 OSEN. - AUTH_TYPE_OSEN = 5; - // IEEE 802.11r Fast BSS Transition with PSK authentication. - AUTH_TYPE_FT_PSK = 6; - // IEEE 802.11r Fast BSS Transition with EAP authentication. - AUTH_TYPE_FT_EAP = 7; - // Simultaneous Authentication of Equals. - AUTH_TYPE_SAE = 8; - // Opportunistic Wireless Encryption. - AUTH_TYPE_OWE = 9; - // SUITE_B_192 192 bit level - AUTH_TYPE_SUITE_B_192 = 10; - // WPA pre-shared key with stronger SHA256-based algorithms. - AUTH_TYPE_WPA_PSK_SHA256 = 11; - // WPA using EAP authentication with stronger SHA256-based algorithms. - AUTH_TYPE_WPA_EAP_SHA256 = 12; - // WAPI pre-shared key. - AUTH_TYPE_WAPI_PSK = 13; - // WAPI certificate to be specified. - AUTH_TYPE_WAPI_CERT = 14; - // IEEE 802.11ai FILS SK with SHA256. - AUTH_TYPE_FILS_SHA256 = 15; - // IEEE 802.11ai FILS SK with SHA384. - AUTH_TYPE_FILS_SHA384 = 16; -} - -/** - * Bucketed wifi band. - */ -enum WifiBandBucket { - BAND_UNKNOWN = 0; - - // All of 2.4GHz band - BAND_2G = 1; - // Frequencies in the range of [5150, 5250) GHz - BAND_5G_LOW = 2; - // Frequencies in the range of [5250, 5725) GHz - BAND_5G_MIDDLE = 3; - // Frequencies in the range of [5725, 5850) GHz - BAND_5G_HIGH = 4; - // Frequencies in the range of [5925, 6425) GHz - BAND_6G_LOW = 5; - // Frequencies in the range of [6425, 6875) GHz - BAND_6G_MIDDLE = 6; - // Frequencies in the range of [6875, 7125) GHz - BAND_6G_HIGH = 7; -}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java index 4b9910c79770..19e7f80dfa5b 100644 --- a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java +++ b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java @@ -42,7 +42,7 @@ public class ApplicationLoadersTest { return new SharedLibraryInfo( zip, null /*packageName*/, null /*codePaths*/, null /*name*/, 0 /*version*/, SharedLibraryInfo.TYPE_BUILTIN, null /*declaringPackage*/, - null /*dependentPackages*/, null /*dependencies*/); + null /*dependentPackages*/, null /*dependencies*/, false /*isNative*/); } @Test diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java index 4fe68cd5a27a..e5da41c7c113 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java @@ -51,6 +51,8 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; import android.hardware.display.DisplayManager; +import android.hardware.display.VirtualDisplay; +import android.os.Bundle; import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.util.DisplayMetrics; @@ -66,6 +68,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.content.ReferrerIntent; +import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -95,6 +98,16 @@ public class ActivityThreadTest { new ActivityTestRule<>(TestActivity.class, true /* initialTouchMode */, false /* launchActivity */); + private ArrayList<VirtualDisplay> mCreatedVirtualDisplays; + + @After + public void tearDown() { + if (mCreatedVirtualDisplays != null) { + mCreatedVirtualDisplays.forEach(VirtualDisplay::release); + mCreatedVirtualDisplays = null; + } + } + @Test public void testDoubleRelaunch() throws Exception { final Activity activity = mActivityTestRule.launchActivity(new Intent()); @@ -410,7 +423,6 @@ public class ActivityThreadTest { Context appContext = activity.getApplication(); Configuration originalAppConfig = new Configuration(appContext.getResources().getConfiguration()); - DisplayManager dm = appContext.getSystemService(DisplayManager.class); int virtualDisplayWidth; int virtualDisplayHeight; @@ -421,8 +433,8 @@ public class ActivityThreadTest { virtualDisplayWidth = 200; virtualDisplayHeight = 100; } - Display virtualDisplay = dm.createVirtualDisplay("virtual-display", - virtualDisplayWidth, virtualDisplayHeight, 200, null, 0).getDisplay(); + final Display virtualDisplay = createVirtualDisplay(appContext, + virtualDisplayWidth, virtualDisplayHeight); Context virtualDisplayContext = appContext.createDisplayContext(virtualDisplay); int originalVirtualDisplayOrientation = virtualDisplayContext.getResources() .getConfiguration().orientation; @@ -467,7 +479,6 @@ public class ActivityThreadTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { Configuration originalActivityConfig = new Configuration(activity.getResources().getConfiguration()); - DisplayManager dm = activity.getSystemService(DisplayManager.class); int virtualDisplayWidth; int virtualDisplayHeight; @@ -478,8 +489,8 @@ public class ActivityThreadTest { virtualDisplayWidth = 200; virtualDisplayHeight = 100; } - Display virtualDisplay = dm.createVirtualDisplay("virtual-display", - virtualDisplayWidth, virtualDisplayHeight, 200, null, 0).getDisplay(); + final Display virtualDisplay = createVirtualDisplay(activity, + virtualDisplayWidth, virtualDisplayHeight); Context virtualDisplayContext = activity.createDisplayContext(virtualDisplay); int originalVirtualDisplayOrientation = virtualDisplayContext.getResources() .getConfiguration().orientation; @@ -704,6 +715,17 @@ public class ActivityThreadTest { return config.seq; } + private Display createVirtualDisplay(Context context, int w, int h) { + final DisplayManager dm = context.getSystemService(DisplayManager.class); + final VirtualDisplay virtualDisplay = dm.createVirtualDisplay("virtual-display", w, h, + 200 /* densityDpi */, null /* surface */, 0 /* flags */); + if (mCreatedVirtualDisplays == null) { + mCreatedVirtualDisplays = new ArrayList<>(); + } + mCreatedVirtualDisplays.add(virtualDisplay); + return virtualDisplay.getDisplay(); + } + private static ActivityClientRecord getActivityClientRecord(Activity activity) { final ActivityThread thread = activity.getActivityThread(); final IBinder token = activity.getActivityToken(); @@ -796,6 +818,14 @@ public class ActivityThreadTest { volatile CountDownLatch mConfigLatch; @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().getDecorView().setKeepScreenOn(true); + setShowWhenLocked(true); + setTurnScreenOn(true); + } + + @Override public void onConfigurationChanged(Configuration config) { super.onConfigurationChanged(config); mConfig.setTo(config); diff --git a/core/tests/coretests/src/android/security/CredentialManagementAppTest.java b/core/tests/coretests/src/android/security/CredentialManagementAppTest.java new file mode 100644 index 000000000000..366aabd183e3 --- /dev/null +++ b/core/tests/coretests/src/android/security/CredentialManagementAppTest.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import android.net.Uri; +import android.util.Xml; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Iterator; +import java.util.Map; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public final class CredentialManagementAppTest { + + private static final String TEST_PACKAGE_NAME_1 = "com.android.test"; + private static final String TEST_PACKAGE_NAME_2 = "com.android.test2"; + private static final Uri TEST_URI_1 = Uri.parse("test.com"); + private static final Uri TEST_URI_2 = Uri.parse("test2.com"); + private static final String TEST_ALIAS_1 = "testAlias"; + private static final String TEST_ALIAS_2 = "testAlias2"; + + private static final String PACKAGE_NAME = "com.android.cred.mng.pkg"; + private static final AppUriAuthenticationPolicy AUTHENTICATION_POLICY = + new AppUriAuthenticationPolicy.Builder() + .addAppAndUriMapping(TEST_PACKAGE_NAME_1, TEST_URI_1, TEST_ALIAS_1) + .build(); + private static final CredentialManagementApp CREDENTIAL_MANAGEMENT_APP = + new CredentialManagementApp(PACKAGE_NAME, AUTHENTICATION_POLICY); + + private static final String TAG_CREDENTIAL_MANAGEMENT_APP = "credential-management-app"; + + @Test + public void credentialManagementApp_getters() { + CredentialManagementApp credentialManagementApp = + new CredentialManagementApp(PACKAGE_NAME, AUTHENTICATION_POLICY); + + assertThat(credentialManagementApp.getPackageName(), is(PACKAGE_NAME)); + assertThat(credentialManagementApp.getAuthenticationPolicy(), is(AUTHENTICATION_POLICY)); + } + + @Test + public void setAuthenticationPolicy_updatesAuthenticationPolicy() { + CredentialManagementApp credentialManagementApp = + new CredentialManagementApp(PACKAGE_NAME, AUTHENTICATION_POLICY); + AppUriAuthenticationPolicy updatedAuthenticationPolicy = + new AppUriAuthenticationPolicy.Builder().addAppAndUriMapping( + TEST_PACKAGE_NAME_2, TEST_URI_2, TEST_ALIAS_2).build(); + + credentialManagementApp.setAuthenticationPolicy(updatedAuthenticationPolicy); + + assertThat(credentialManagementApp.getAuthenticationPolicy(), + is(updatedAuthenticationPolicy)); + } + + @Test + public void constructor_nullPackageName_throwException() { + try { + new CredentialManagementApp(/* packageName= */ null, AUTHENTICATION_POLICY); + fail("Shall not take null inputs"); + } catch (NullPointerException expected) { + // Expected behavior, nothing to do. + } + } + + @Test + public void constructor_nullAuthenticationPolicy_throwException() { + try { + new CredentialManagementApp(PACKAGE_NAME, /* authenticationPolicy= */ null); + fail("Shall not take null inputs"); + } catch (NullPointerException expected) { + // Expected behavior, nothing to do. + } + } + + @Test + public void writeToXmlAndReadFromXml() throws IOException, XmlPullParserException { + File xmlFile = writeToXml(CREDENTIAL_MANAGEMENT_APP); + + CredentialManagementApp loadedCredentialManagementApp = readFromXml(xmlFile); + + assertCredentialManagementAppsEqual(loadedCredentialManagementApp, + CREDENTIAL_MANAGEMENT_APP); + } + + private File writeToXml(CredentialManagementApp credentialManagementApp) throws IOException { + File file = File.createTempFile("temp", "credmng"); + final FileOutputStream out = new FileOutputStream(file); + XmlSerializer xml = Xml.newSerializer(); + xml.setOutput(out, StandardCharsets.UTF_8.name()); + xml.startDocument(null, true); + xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); + xml.startTag(null, TAG_CREDENTIAL_MANAGEMENT_APP); + credentialManagementApp.writeToXml(xml); + xml.endTag(null, TAG_CREDENTIAL_MANAGEMENT_APP); + xml.endDocument(); + out.close(); + return file; + } + + private CredentialManagementApp readFromXml(File file) + throws IOException, XmlPullParserException { + CredentialManagementApp credentialManagementApp = null; + final XmlPullParser parser = Xml.newPullParser(); + final FileInputStream in = new FileInputStream(file); + parser.setInput(in, StandardCharsets.UTF_8.name()); + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + } + String tag = parser.getName(); + if (TAG_CREDENTIAL_MANAGEMENT_APP.equals(tag)) { + credentialManagementApp = CredentialManagementApp.readFromXml(parser); + } + return credentialManagementApp; + } + + private void assertCredentialManagementAppsEqual(CredentialManagementApp actual, + CredentialManagementApp expected) { + assertThat(actual.getPackageName(), is(expected.getPackageName())); + assertAuthenticationPoliciesEqual(actual.getAuthenticationPolicy(), + expected.getAuthenticationPolicy()); + } + + private void assertAuthenticationPoliciesEqual(AppUriAuthenticationPolicy actual, + AppUriAuthenticationPolicy expected) { + Iterator<Map.Entry<String, Map<Uri, String>>> actualIter = + actual.getAppAndUriMappings().entrySet().iterator(); + Iterator<Map.Entry<String, Map<Uri, String>>> expectedIter = + expected.getAppAndUriMappings().entrySet().iterator(); + + assertThat(actual.getAppAndUriMappings().size(), + is(expected.getAppAndUriMappings().size())); + while (actualIter.hasNext()) { + Map.Entry<String, Map<Uri, String>> actualAppToUri = actualIter.next(); + Map.Entry<String, Map<Uri, String>> expectedAppToUri = expectedIter.next(); + assertThat(actualAppToUri.getKey(), is(expectedAppToUri.getKey())); + assertUrisToAliasesEqual(actualAppToUri.getValue(), expectedAppToUri.getValue()); + } + } + + private void assertUrisToAliasesEqual(Map<Uri, String> actual, Map<Uri, String> expected) { + Iterator<Map.Entry<Uri, String>> actualIter = actual.entrySet().iterator(); + Iterator<Map.Entry<Uri, String>> expectedIter = expected.entrySet().iterator(); + + assertThat(actual.size(), is(expected.size())); + while (actualIter.hasNext()) { + Map.Entry<Uri, String> actualUriToAlias = actualIter.next(); + Map.Entry<Uri, String> expectedUriToAlias = expectedIter.next(); + assertThat(actualUriToAlias.getKey(), is(expectedUriToAlias.getKey())); + assertThat(actualUriToAlias.getValue(), is(expectedUriToAlias.getValue())); + } + } +} diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index 7cde19c30dd4..40ef04a5e369 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -376,6 +376,56 @@ public class TextViewActivityTest { } @Test + public void testToolbarMenuItemClickAfterSelectionChange() throws Throwable { + final MenuItem[] latestItem = new MenuItem[1]; + final MenuItem[] clickedItem = new MenuItem[1]; + final String text = "abcd efg hijk"; + mActivityRule.runOnUiThread(() -> { + final TextView textView = mActivity.findViewById(R.id.textview); + textView.setText(text); + textView.setCustomSelectionActionModeCallback( + new ActionMode.Callback() { + @Override + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + menu.clear(); + latestItem[0] = menu.add("Item"); + return true; + } + + @Override + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + clickedItem[0] = item; + return true; + } + + @Override + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + return true; + } + + @Override + public void onDestroyActionMode(ActionMode mode) {} + }); + }); + mInstrumentation.waitForIdleSync(); + + onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("f"))); + sleepForFloatingToolbarPopup(); + + // Change the selection so that the menu items are refreshed. + final TextView textView = mActivity.findViewById(R.id.textview); + onHandleView(com.android.internal.R.id.selection_start_handle) + .perform(dragHandle(textView, Handle.SELECTION_START, 0)); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + + clickFloatingToolbarItem("Item"); + mInstrumentation.waitForIdleSync(); + + assertEquals(latestItem[0], clickedItem[0]); + } + + @Test public void testSelectionRemovedWhenNonselectableTextLosesFocus() throws Throwable { final TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview); final int position = (textLink.getStart() + textLink.getEnd()) / 2; diff --git a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java index d45d4b04af33..477978630ec2 100644 --- a/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java +++ b/core/tests/coretests/src/android/widget/espresso/FloatingToolbarEspressoUtils.java @@ -28,10 +28,11 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withTagValue; import static androidx.test.espresso.matcher.ViewMatchers.withText; +import static com.android.internal.widget.FloatingToolbar.MenuItemRepr; + import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.is; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -158,8 +159,8 @@ public class FloatingToolbarEspressoUtils { public void describeTo(Description description) {} private void collectMenuItemIds(View view) { - if (view.getTag() instanceof MenuItem) { - menuItemIds.add(((MenuItem) view.getTag()).getItemId()); + if (view.getTag() instanceof MenuItemRepr) { + menuItemIds.add(((MenuItemRepr) view.getTag()).itemId); } else if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0; i < viewGroup.getChildCount(); i++) { @@ -178,8 +179,8 @@ public class FloatingToolbarEspressoUtils { */ public static void assertFloatingToolbarDoesNotContainItem(String itemLabel) { final Predicate<View> hasMenuItemLabel = view -> - view.getTag() instanceof MenuItem - && itemLabel.equals(((MenuItem) view.getTag()).getTitle().toString()); + view.getTag() instanceof MenuItemRepr + && itemLabel.equals(((MenuItemRepr) view.getTag()).title); assertFloatingToolbarMenuItem(hasMenuItemLabel, false); } @@ -191,8 +192,8 @@ public class FloatingToolbarEspressoUtils { */ public static void assertFloatingToolbarDoesNotContainItem(final int menuItemId) { final Predicate<View> hasMenuItemId = view -> - view.getTag() instanceof MenuItem - && ((MenuItem) view.getTag()).getItemId() == menuItemId; + view.getTag() instanceof MenuItemRepr + && ((MenuItemRepr) view.getTag()).itemId == menuItemId; assertFloatingToolbarMenuItem(hasMenuItemId, false); } diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 10310237f89b..a52eca7e0d73 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1561,6 +1561,12 @@ "group": "WM_DEBUG_WINDOW_TRANSITIONS", "at": "com\/android\/server\/wm\/Transition.java" }, + "-292790591": { + "message": "Attempted to set IME policy to a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, "-279436615": { "message": "Moving to PAUSING: %s", "level": "VERBOSE", @@ -1819,12 +1825,6 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/ActivityTaskManagerService.java" }, - "91350919": { - "message": "Attempted to set IME flag to a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "94402792": { "message": "Moving to RESUMED: %s (in existing)", "level": "VERBOSE", @@ -1837,12 +1837,6 @@ "group": "WM_DEBUG_IME", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "95281111": { - "message": "Attempted to get IME flag of a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "95902367": { "message": "Relayout of %s: focusMayChange=%b", "level": "VERBOSE", @@ -2749,6 +2743,12 @@ "group": "WM_SHOW_SURFACE_ALLOC", "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" }, + "1100065297": { + "message": "Attempted to get IME policy of a display that does not exist: %d", + "level": "WARN", + "group": "WM_ERROR", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, "1112047265": { "message": "finishDrawingWindow: %s mDrawState=%s", "level": "DEBUG", diff --git a/core/proto/android/stats/storage/storage_enums.proto b/keystore/java/android/security/AppUriAuthenticationPolicy.aidl index 6892e287472f..5c52c86f0426 100644 --- a/core/proto/android/stats/storage/storage_enums.proto +++ b/keystore/java/android/security/AppUriAuthenticationPolicy.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +14,6 @@ * limitations under the License. */ -syntax = "proto2"; +package android.security; -package android.stats.storage; - -enum ExternalStorageType { - UNKNOWN = 0; - SD_CARD = 1; - USB = 2; - OTHER = 3; -} +parcelable AppUriAuthenticationPolicy; diff --git a/keystore/java/android/security/AppUriAuthenticationPolicy.java b/keystore/java/android/security/AppUriAuthenticationPolicy.java new file mode 100644 index 000000000000..30f5a94ca0c8 --- /dev/null +++ b/keystore/java/android/security/AppUriAuthenticationPolicy.java @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * The app-URI authentication policy is set by the credential management app. This policy determines + * which alias for a private key and certificate pair should be used for authentication. + * <p> + * The authentication policy should be added as a parameter when calling + * {@link KeyChain#createManageCredentialsIntent}. + * <p> + * Example: + * <pre>{@code + * AppUriAuthenticationPolicy authenticationPolicy = new AppUriAuthenticationPolicy.Builder() + * .addAppAndUriMapping("com.test.pkg", testUri, "testAlias") + * .addAppAndUriMapping("com.test2.pkg", testUri1, "testAlias2") + * .addAppAndUriMapping("com.test2.pkg", testUri2, "testAlias2") + * .build(); + * Intent requestIntent = KeyChain.createManageCredentialsIntent(authenticationPolicy); + * }</pre> + * <p> + */ +public final class AppUriAuthenticationPolicy implements Parcelable { + + private static final String KEY_AUTHENTICATION_POLICY_APP_TO_URIS = + "authentication_policy_app_to_uris"; + private static final String KEY_AUTHENTICATION_POLICY_APP = "policy_app"; + + /** + * The mappings from an app and list of URIs to a list of aliases, which will be used for + * authentication. + * <p> + * appPackageName -> uri -> alias + */ + @NonNull + private final Map<String, UrisToAliases> mAppToUris; + + private AppUriAuthenticationPolicy(@NonNull Map<String, UrisToAliases> appToUris) { + Objects.requireNonNull(appToUris); + this.mAppToUris = appToUris; + } + + /** + * Builder class for {@link AppUriAuthenticationPolicy} objects. + */ + public static final class Builder { + private Map<String, UrisToAliases> mPackageNameToUris; + + /** + * Initialize a new Builder to construct an {@link AppUriAuthenticationPolicy}. + */ + public Builder() { + mPackageNameToUris = new HashMap<>(); + } + + /** + * Adds mappings from an app and URI to an alias, which will be used for authentication. + * <p> + * If this method is called with a package name and URI that was previously added, the + * previous alias will be overwritten. + * + * @param appPackageName The app's package name to authenticate the user to. + * @param uri The URI to authenticate the user to. + * @param alias The alias which will be used for authentication. + * + * @return the same Builder instance. + */ + @NonNull + public Builder addAppAndUriMapping(@NonNull String appPackageName, @NonNull Uri uri, + @NonNull String alias) { + Objects.requireNonNull(appPackageName); + Objects.requireNonNull(uri); + Objects.requireNonNull(alias); + UrisToAliases urisToAliases = + mPackageNameToUris.getOrDefault(appPackageName, new UrisToAliases()); + urisToAliases.addUriToAlias(uri, alias); + mPackageNameToUris.put(appPackageName, urisToAliases); + return this; + } + + /** + * Adds mappings from an app and list of URIs to a list of aliases, which will be used for + * authentication. + * <p> + * appPackageName -> uri -> alias + * + * @hide + */ + @NonNull + public Builder addAppAndUriMapping(@NonNull String appPackageName, + @NonNull UrisToAliases urisToAliases) { + Objects.requireNonNull(appPackageName); + Objects.requireNonNull(urisToAliases); + mPackageNameToUris.put(appPackageName, urisToAliases); + return this; + } + + /** + * Combines all of the attributes that have been set on the {@link Builder} + * + * @return a new {@link AppUriAuthenticationPolicy} object. + */ + @NonNull + public AppUriAuthenticationPolicy build() { + return new AppUriAuthenticationPolicy(mPackageNameToUris); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeMap(mAppToUris); + } + + @NonNull + public static final Parcelable.Creator<AppUriAuthenticationPolicy> CREATOR = + new Parcelable.Creator<AppUriAuthenticationPolicy>() { + @Override + public AppUriAuthenticationPolicy createFromParcel(Parcel in) { + Map<String, UrisToAliases> appToUris = new HashMap<>(); + in.readMap(appToUris, UrisToAliases.class.getClassLoader()); + return new AppUriAuthenticationPolicy(appToUris); + } + + @Override + public AppUriAuthenticationPolicy[] newArray(int size) { + return new AppUriAuthenticationPolicy[size]; + } + }; + + @Override + public String toString() { + return "AppUriAuthenticationPolicy{" + + "mPackageNameToUris=" + mAppToUris + + '}'; + } + + /** + * Return the authentication policy mapping, which determines which alias for a private key + * and certificate pair should be used for authentication. + * <p> + * appPackageName -> uri -> alias + */ + @NonNull + public Map<String, Map<Uri, String>> getAppAndUriMappings() { + Map<String, Map<Uri, String>> appAndUris = new HashMap<>(); + for (Map.Entry<String, UrisToAliases> entry : mAppToUris.entrySet()) { + appAndUris.put(entry.getKey(), entry.getValue().getUrisToAliases()); + } + return appAndUris; + } + + /** + * Restore a previously saved {@link AppUriAuthenticationPolicy} from XML. + * + * @hide + */ + @Nullable + public static AppUriAuthenticationPolicy readFromXml(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + AppUriAuthenticationPolicy.Builder builder = new AppUriAuthenticationPolicy.Builder(); + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + if (!parser.getName().equals(KEY_AUTHENTICATION_POLICY_APP_TO_URIS)) { + continue; + } + String app = parser.getAttributeValue(null, KEY_AUTHENTICATION_POLICY_APP); + UrisToAliases urisToAliases = UrisToAliases.readFromXml(parser); + builder.addAppAndUriMapping(app, urisToAliases); + } + return builder.build(); + } + + /** + * Save the {@link AppUriAuthenticationPolicy} to XML. + * + * @hide + */ + public void writeToXml(@NonNull XmlSerializer out) throws IOException { + for (Map.Entry<String, UrisToAliases> appsToUris : mAppToUris.entrySet()) { + out.startTag(null, KEY_AUTHENTICATION_POLICY_APP_TO_URIS); + out.attribute(null, KEY_AUTHENTICATION_POLICY_APP, appsToUris.getKey()); + appsToUris.getValue().writeToXml(out); + out.endTag(null, KEY_AUTHENTICATION_POLICY_APP_TO_URIS); + } + } + +} diff --git a/keystore/java/android/security/CredentialManagementApp.java b/keystore/java/android/security/CredentialManagementApp.java new file mode 100644 index 000000000000..cbb23015dbe8 --- /dev/null +++ b/keystore/java/android/security/CredentialManagementApp.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.Log; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.Objects; + +/** + * The credential management app has the ability to manage the user's KeyChain credentials on + * unmanaged devices. {@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. + * <p> + * Note: there can only be one credential management on the device. If another app requests to + * become the credential management app and the user approves, then the existing credential + * management app will no longer be able to manage credentials. + * <p> + * The requesting credential management app should include its authentication policy in the + * requesting intent. The authentication policy declares which certificates should be used for a + * given list of apps and URIs. + * + * @hide + * @see AppUriAuthenticationPolicy + */ +public class CredentialManagementApp { + + private static final String TAG = "CredentialManagementApp"; + private static final String KEY_PACKAGE_NAME = "package_name"; + + /** + * The credential management app's package name + */ + @NonNull + private final String mPackageName; + + /** + * The mappings from an app and list of URIs to a list of aliases, which will be used for + * authentication. + * <p> + * appPackageName -> uri -> alias + */ + @NonNull + private AppUriAuthenticationPolicy mAuthenticationPolicy; + + public CredentialManagementApp(@NonNull String packageName, + @NonNull AppUriAuthenticationPolicy authenticationPolicy) { + Objects.requireNonNull(packageName); + Objects.requireNonNull(authenticationPolicy); + mPackageName = packageName; + mAuthenticationPolicy = authenticationPolicy; + } + + /** + * Returns the package name of the credential management app. + */ + @NonNull + public String getPackageName() { + return mPackageName; + } + + /** + * Returns the authentication policy of the credential management app. + */ + @NonNull + public AppUriAuthenticationPolicy getAuthenticationPolicy() { + return mAuthenticationPolicy; + } + + /** + * Sets the authentication policy of the credential management app. + */ + public void setAuthenticationPolicy(@Nullable AppUriAuthenticationPolicy authenticationPolicy) { + Objects.requireNonNull(authenticationPolicy); + mAuthenticationPolicy = authenticationPolicy; + } + + /** + * Restore a previously saved {@link CredentialManagementApp} from XML. + */ + @Nullable + public static CredentialManagementApp readFromXml(@NonNull XmlPullParser parser) { + try { + String packageName = parser.getAttributeValue(null, KEY_PACKAGE_NAME); + AppUriAuthenticationPolicy policy = AppUriAuthenticationPolicy.readFromXml(parser); + return new CredentialManagementApp(packageName, policy); + } catch (XmlPullParserException | IOException e) { + Log.w(TAG, "Reading from xml failed", e); + } + return null; + } + + /** + * Save the {@link CredentialManagementApp} to XML. + */ + public void writeToXml(@NonNull XmlSerializer out) throws IOException { + out.attribute(null, KEY_PACKAGE_NAME, mPackageName); + if (mAuthenticationPolicy != null) { + mAuthenticationPolicy.writeToXml(out); + } + } +} diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java index 7abcfdc98bc6..f41b6081e38c 100644 --- a/keystore/java/android/security/Credentials.java +++ b/keystore/java/android/security/Credentials.java @@ -49,6 +49,8 @@ public class Credentials { public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER"; + public static final String ACTION_MANAGE_CREDENTIALS = "android.security.MANAGE_CREDENTIALS"; + /** * Key prefix for CA certificates. * diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index a77aec2788af..c6e72b0e9f6e 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -15,6 +15,8 @@ */ package android.security; +import static android.security.Credentials.ACTION_MANAGE_CREDENTIALS; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SdkConstant; @@ -122,6 +124,11 @@ public final class KeyChain { private static final String CERT_INSTALLER_PACKAGE = "com.android.certinstaller"; /** + * Package name for Settings. + */ + private static final String SETTINGS_PACKAGE = "com.android.settings"; + + /** * Extra for use with {@link #ACTION_CHOOSER} * @hide Also used by KeyChainActivity implementation */ @@ -202,6 +209,20 @@ public final class KeyChain { public static final String EXTRA_PKCS12 = "PKCS12"; /** + * Extra used by {@link #createManageCredentialsIntent(AppUriAuthenticationPolicy)} to specify + * the authentication policy of the credential management app. + * + * <p>The authentication policy declares which alias for a private key and certificate pair + * should be used for authentication, given a list of apps and URIs. + * + * <p>The extra value should be a {@link AppUriAuthenticationPolicy}. + * + * @hide + */ + public static final String EXTRA_AUTHENTICATION_POLICY = + "android.security.extra.AUTHENTICATION_POLICY"; + + /** * Broadcast Action: Indicates the trusted storage has changed. Sent when * one of this happens: * @@ -386,6 +407,23 @@ public final class KeyChain { } /** + * Returns an {@code Intent} that should be used by an app to request to manage the user's + * credentials. This is limited to unmanaged devices. The authentication policy must be + * provided to be able to make this request successfully. + * + * @param policy The authentication policy determines which alias for a private key and + * certificate pair should be used for authentication. + */ + @NonNull + public static Intent createManageCredentialsIntent(@NonNull AppUriAuthenticationPolicy policy) { + Intent intent = new Intent(ACTION_MANAGE_CREDENTIALS); + intent.setComponent(ComponentName.createRelative(SETTINGS_PACKAGE, + ".security.RequestManageCredentials")); + intent.putExtra(EXTRA_AUTHENTICATION_POLICY, policy); + return intent; + } + + /** * Launches an {@code Activity} for the user to select the alias * for a private key and certificate pair for authentication. The * selected alias or null will be returned via the diff --git a/keystore/java/android/security/UrisToAliases.java b/keystore/java/android/security/UrisToAliases.java new file mode 100644 index 000000000000..65d433abe166 --- /dev/null +++ b/keystore/java/android/security/UrisToAliases.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * The mapping from URI to alias, which determines the alias to use when the user visits a URI. + * This mapping is part of the {@link AppUriAuthenticationPolicy}, which specifies which app this + * mapping should be used for. + * + * @hide + * @see AppUriAuthenticationPolicy + */ +public final class UrisToAliases implements Parcelable { + + private static final String KEY_AUTHENTICATION_POLICY_URI_TO_ALIAS = + "authentication_policy_uri_to_alias"; + private static final String KEY_AUTHENTICATION_POLICY_URI = "policy_uri"; + private static final String KEY_AUTHENTICATION_POLICY_ALIAS = "policy_alias"; + + /** + * The mappings from URIs to aliases, which will be used for authentication. + */ + @NonNull + private final Map<Uri, String> mUrisToAliases; + + public UrisToAliases() { + this.mUrisToAliases = new HashMap<>(); + } + + private UrisToAliases(@NonNull Map<Uri, String> urisToAliases) { + this.mUrisToAliases = urisToAliases; + } + + @NonNull + public static final Creator<UrisToAliases> CREATOR = new Creator<UrisToAliases>() { + @Override + public UrisToAliases createFromParcel(Parcel in) { + Map<Uri, String> urisToAliases = new HashMap<>(); + in.readMap(urisToAliases, String.class.getClassLoader()); + return new UrisToAliases(urisToAliases); + } + + @Override + public UrisToAliases[] newArray(int size) { + return new UrisToAliases[size]; + } + }; + + /** + * Returns the mapping from URIs to aliases. + */ + @NonNull + public Map<Uri, String> getUrisToAliases() { + return Collections.unmodifiableMap(mUrisToAliases); + } + + /** + * Adds mapping from an URI to an alias. + */ + public void addUriToAlias(@NonNull Uri uri, @NonNull String alias) { + mUrisToAliases.put(uri, alias); + } + + /** + * Restore a previously saved {@link UrisToAliases} from XML. + */ + @Nullable + public static UrisToAliases readFromXml(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + Map<Uri, String> urisToAliases = new HashMap<>(); + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + if (!parser.getName().equals(KEY_AUTHENTICATION_POLICY_URI_TO_ALIAS)) { + continue; + } + Uri uri = Uri.parse(parser.getAttributeValue(null, KEY_AUTHENTICATION_POLICY_URI)); + String alias = parser.getAttributeValue(null, KEY_AUTHENTICATION_POLICY_ALIAS); + urisToAliases.put(uri, alias); + } + return new UrisToAliases(urisToAliases); + } + + /** + * Save the {@link UrisToAliases} to XML. + */ + public void writeToXml(@NonNull XmlSerializer out) throws IOException { + for (Map.Entry<Uri, String> urisToAliases : mUrisToAliases.entrySet()) { + out.startTag(null, KEY_AUTHENTICATION_POLICY_URI_TO_ALIAS); + out.attribute(null, KEY_AUTHENTICATION_POLICY_URI, urisToAliases.getKey().toString()); + out.attribute(null, KEY_AUTHENTICATION_POLICY_ALIAS, urisToAliases.getValue()); + out.endTag(null, KEY_AUTHENTICATION_POLICY_URI_TO_ALIAS); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeMap(mUrisToAliases); + } +} diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java index 5867ef6eaea5..b1b6306e0cf6 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java @@ -83,8 +83,7 @@ public class AndroidKeyStoreProvider extends Provider { boolean supports3DES = "true".equals(android.os.SystemProperties.get(DESEDE_SYSTEM_PROPERTY)); // java.security.KeyStore - put("KeyStore.AndroidKeyStore", PACKAGE_NAME + ".AndroidKeyStoreSpi"); - put("Alg.Alias.KeyStore.AndroidKeyStoreLegacy", "AndroidKeyStore"); + put("KeyStore." + providerName, PACKAGE_NAME + ".AndroidKeyStoreSpi"); // java.security.KeyPairGenerator put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC"); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java index 388eb28223dc..120039de1240 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java @@ -116,7 +116,7 @@ public class Transitions extends ITransitionPlayer.Stub { } @Override - public void onTransitionReady(@NonNull IBinder transitionToken, TransitionInfo info, + public void onTransitionReady(@NonNull IBinder transitionToken, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "onTransitionReady %s: %s", transitionToken, info); @@ -131,22 +131,53 @@ public class Transitions extends ITransitionPlayer.Stub { + transitionToken); } mActiveTransitions.put(transitionToken, new ArrayList<>()); - for (int i = 0; i < info.getChanges().size(); ++i) { - final SurfaceControl leash = info.getChanges().get(i).getLeash(); + boolean isOpening = isOpeningType(info.getType()); + if (info.getRootLeash().isValid()) { + t.show(info.getRootLeash()); + } + // changes should be ordered top-to-bottom in z + for (int i = info.getChanges().size() - 1; i >= 0; --i) { + final TransitionInfo.Change change = info.getChanges().get(i); + final SurfaceControl leash = change.getLeash(); final int mode = info.getChanges().get(i).getMode(); + + // Don't animate anything with an animating parent + if (change.getParent() != null) { + if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) { + t.show(leash); + t.setMatrix(leash, 1, 0, 0, 1); + } + continue; + } + + t.reparent(leash, info.getRootLeash()); + t.setPosition(leash, change.getEndAbsBounds().left - info.getRootOffset().x, + change.getEndAbsBounds().top - info.getRootOffset().y); + // Put all the OPEN/SHOW on top if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) { t.show(leash); t.setMatrix(leash, 1, 0, 0, 1); - if (isOpeningType(info.getType())) { + if (isOpening) { + // put on top and fade in + t.setLayer(leash, info.getChanges().size() - i); t.setAlpha(leash, 0.f); startExampleAnimation(transitionToken, leash, true /* show */); } else { + // put on bottom and leave it visible without fade + t.setLayer(leash, -i); t.setAlpha(leash, 1.f); } } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_HIDE) { - if (!isOpeningType(info.getType())) { + if (isOpening) { + // put on bottom and leave visible without fade + t.setLayer(leash, -i); + } else { + // put on top and fade out + t.setLayer(leash, info.getChanges().size() - i); startExampleAnimation(transitionToken, leash, false /* show */); } + } else { + t.setLayer(leash, info.getChanges().size() - i); } } t.apply(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java index 090d2270817b..4e62ea6e7233 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java @@ -272,8 +272,9 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { @VisibleForTesting void applyBoundsAndOffsets(WindowContainerToken token, SurfaceControl leash, WindowContainerTransaction wct, SurfaceControl.Transaction t) { - wct.setBounds(token, mCurrentDisplayBounds.isEmpty() ? null : mCurrentDisplayBounds); + wct.setBounds(token, mCurrentDisplayBounds); t.setPosition(leash, mOffsetX, mOffsetY); + t.setWindowCrop(leash, mCurrentDisplayBounds.width(), mCurrentDisplayBounds.height()); } @VisibleForTesting diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp index 1bbe6884a48c..4a498d2ec581 100644 --- a/libs/WindowManager/Shell/tests/flicker/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/Android.bp @@ -33,6 +33,7 @@ android_test { "wm-flicker-common-assertions", "wm-flicker-common-app-helpers", "platform-test-annotations", + "wmshell-flicker-test-components", ], } @@ -54,5 +55,6 @@ android_test { "wm-flicker-common-assertions", "wm-flicker-common-app-helpers", "platform-test-annotations", + "wmshell-flicker-test-components", ], } diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml index 9e8330973b40..101b5bf27c77 100644 --- a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml +++ b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml @@ -36,6 +36,8 @@ <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/> <!-- Control test app's media session --> <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/> + <!-- ATM.removeRootTasksWithActivityTypes() --> + <uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS" /> <application> <uses-library android:name="android.test.runner"/> 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 bbf5afcff67a..96234fcc8570 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 @@ -16,35 +16,24 @@ package com.android.wm.shell.flicker -import android.content.ComponentName - const val IME_WINDOW_NAME = "InputMethod" -const val PIP_WINDOW_NAME = "PipMenuActivity" -const val SPLITSCREEN_PRIMARY_WINDOW_NAME = "SplitScreenActivity" -const val SPLITSCREEN_SECONDARY_WINDOW_NAME = "SplitScreenSecondaryActivity" +const val PIP_MENU_WINDOW_NAME = "PipMenuActivity" const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui" const val TEST_APP_PACKAGE_NAME = "com.android.wm.shell.flicker.testapp" // Test App > Pip Activity -val TEST_APP_PIP_ACTIVITY_COMPONENT_NAME: ComponentName = ComponentName.createRelative( - TEST_APP_PACKAGE_NAME, ".PipActivity") const val TEST_APP_PIP_ACTIVITY_LABEL = "PipApp" -const val TEST_APP_PIP_ACTIVITY_WINDOW_NAME = "PipActivity" const val TEST_APP_PIP_MENU_ACTION_NO_OP = "No-Op" const val TEST_APP_PIP_MENU_ACTION_ON = "On" const val TEST_APP_PIP_MENU_ACTION_OFF = "Off" const val TEST_APP_PIP_MENU_ACTION_CLEAR = "Clear" // Test App > Ime Activity -val TEST_APP_IME_ACTIVITY_COMPONENT_NAME: ComponentName = ComponentName.createRelative( - TEST_APP_PACKAGE_NAME, ".ImeActivity") const val TEST_APP_IME_ACTIVITY_LABEL = "ImeApp" +// Test App > Test Activity +const val TEST_APP_FIXED_ACTIVITY_LABEL = "FixedApp" // Test App > SplitScreen Activity -val TEST_APP_SPLITSCREEN_PRIMARY_COMPONENT_NAME: ComponentName = ComponentName.createRelative( - TEST_APP_PACKAGE_NAME, ".$SPLITSCREEN_PRIMARY_WINDOW_NAME") -val TEST_APP_SPLITSCREEN_SECONDARY_COMPONENT_NAME: ComponentName = ComponentName.createRelative( - TEST_APP_PACKAGE_NAME, ".$SPLITSCREEN_SECONDARY_WINDOW_NAME") const val TEST_APP_SPLITSCREEN_PRIMARY_LABEL = "SplitScreenPrimaryApp" const val TEST_APP_SPLITSCREEN_SECONDARY_LABEL = "SplitScreenSecondaryApp" diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt index 1a4de0a80bec..f32cd8842074 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt @@ -17,12 +17,11 @@ package com.android.wm.shell.flicker.apppairs import com.android.wm.shell.flicker.NonRotationTestBase -import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_COMPONENT_NAME import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL -import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_COMPONENT_NAME import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL import com.android.wm.shell.flicker.helpers.AppPairsHelper import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import com.android.wm.shell.flicker.testapp.Components abstract class AppPairsTestBase( rotationName: String, @@ -30,11 +29,11 @@ abstract class AppPairsTestBase( ) : NonRotationTestBase(rotationName, rotation) { protected val appPairsHelper = AppPairsHelper(instrumentation, TEST_APP_SPLITSCREEN_PRIMARY_LABEL, - TEST_APP_SPLITSCREEN_PRIMARY_COMPONENT_NAME) + Components.SplitScreenActivity()) protected val primaryApp = SplitScreenHelper(instrumentation, TEST_APP_SPLITSCREEN_PRIMARY_LABEL, - TEST_APP_SPLITSCREEN_PRIMARY_COMPONENT_NAME) + Components.SplitScreenActivity()) protected val secondaryApp = SplitScreenHelper(instrumentation, TEST_APP_SPLITSCREEN_SECONDARY_LABEL, - TEST_APP_SPLITSCREEN_SECONDARY_COMPONENT_NAME) + Components.SplitScreenSecondaryActivity()) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt index 3b6fcdbee4be..e2cda7ad123d 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/AppPairsHelper.kt @@ -17,19 +17,19 @@ package com.android.wm.shell.flicker.helpers import android.app.Instrumentation -import android.content.ComponentName import android.graphics.Region import android.system.helpers.ActivityHelper import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.wm.shell.flicker.testapp.Components class AppPairsHelper( instrumentation: Instrumentation, activityLabel: String, - componentName: ComponentName + componentsInfo: Components.ComponentsInfo ) : BaseAppHelper( instrumentation, activityLabel, - componentName + componentsInfo ) { val activityHelper = ActivityHelper.getInstance() diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt index 22496a506e0d..6fd1df3b3f30 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.helpers import android.app.Instrumentation -import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageManager.FEATURE_LEANBACK @@ -28,15 +27,15 @@ import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiObject2 import androidx.test.uiautomator.Until import com.android.server.wm.flicker.helpers.StandardAppHelper -import com.android.wm.shell.flicker.TEST_APP_PACKAGE_NAME +import com.android.wm.shell.flicker.testapp.Components abstract class BaseAppHelper( instrumentation: Instrumentation, launcherName: String, - private val launcherActivityComponent: ComponentName + private val componentsInfo: Components.ComponentsInfo ) : StandardAppHelper( instrumentation, - TEST_APP_PACKAGE_NAME, + Components.PACKAGE_NAME, launcherName, LauncherStrategyFactory.getInstance(instrumentation).launcherStrategy ) { @@ -53,7 +52,7 @@ abstract class BaseAppHelper( } val defaultWindowName: String - get() = launcherActivityComponent.className + get() = componentsInfo.activityName val label: String get() = context.packageManager.run { @@ -63,8 +62,12 @@ abstract class BaseAppHelper( val ui: UiObject2? get() = uiDevice.findObject(appSelector) - fun launchViaIntent() { - context.startActivity(openAppIntent) + fun launchViaIntent(stringExtras: Map<String, String> = mapOf()) { + val intent = openAppIntent + stringExtras.forEach() { + intent.putExtra(it.key, it.value) + } + context.startActivity(intent) uiDevice.wait(Until.hasObject(appSelector), APP_LAUNCH_WAIT_TIME_MS) } @@ -75,7 +78,7 @@ abstract class BaseAppHelper( override fun getOpenAppIntent(): Intent { val intent = Intent() - intent.component = launcherActivityComponent + intent.component = componentsInfo.componentName intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) return intent } diff --git a/core/proto/android/stats/accessibility/accessibility_enums.proto b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FixedAppHelper.kt index 5118ad5a322c..c7f19a5d2620 100644 --- a/core/proto/android/stats/accessibility/accessibility_enums.proto +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FixedAppHelper.kt @@ -14,22 +14,16 @@ * limitations under the License. */ -syntax = "proto2"; -package android.stats.accessibility; -option java_multiple_files = true; +package com.android.wm.shell.flicker.helpers -// The entry point of the accessibility shortcut. -enum ShortcutType { - UNKNOWN_TYPE = 0; - A11Y_BUTTON = 1; - VOLUME_KEY = 2; - TRIPLE_TAP = 3; - A11Y_BUTTON_LONG_PRESS = 4; -} +import android.app.Instrumentation +import com.android.wm.shell.flicker.TEST_APP_FIXED_ACTIVITY_LABEL +import com.android.wm.shell.flicker.testapp.Components -// The service status code. -enum ServiceStatus { - UNKNOWN = 0; - ENABLED = 1; - DISABLED = 2; -}
\ No newline at end of file +class FixedAppHelper( + instrumentation: Instrumentation +) : BaseAppHelper( + instrumentation, + TEST_APP_FIXED_ACTIVITY_LABEL, + Components.FixedActivity() +)
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt index a6650d7f13d1..d580104ade19 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt @@ -21,8 +21,8 @@ import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import com.android.server.wm.flicker.helpers.FIND_TIMEOUT import com.android.server.wm.flicker.helpers.waitForIME -import com.android.wm.shell.flicker.TEST_APP_IME_ACTIVITY_COMPONENT_NAME import com.android.wm.shell.flicker.TEST_APP_IME_ACTIVITY_LABEL +import com.android.wm.shell.flicker.testapp.Components import org.junit.Assert open class ImeAppHelper( @@ -30,7 +30,7 @@ open class ImeAppHelper( ) : BaseAppHelper( instrumentation, TEST_APP_IME_ACTIVITY_LABEL, - TEST_APP_IME_ACTIVITY_COMPONENT_NAME + Components.ImeActivity() ) { fun openIME() { val editText = uiDevice.wait( diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt index e85ba9ef6da2..ed5f8a42258b 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt @@ -26,8 +26,8 @@ import androidx.test.uiautomator.Until import com.android.server.wm.flicker.helpers.closePipWindow import com.android.server.wm.flicker.helpers.hasPipWindow import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME -import com.android.wm.shell.flicker.TEST_APP_PIP_ACTIVITY_COMPONENT_NAME import com.android.wm.shell.flicker.TEST_APP_PIP_ACTIVITY_LABEL +import com.android.wm.shell.flicker.testapp.Components import org.junit.Assert.assertNotNull import org.junit.Assert.fail @@ -36,7 +36,7 @@ class PipAppHelper( ) : BaseAppHelper( instrumentation, TEST_APP_PIP_ACTIVITY_LABEL, - TEST_APP_PIP_ACTIVITY_COMPONENT_NAME + Components.PipActivity() ) { private val mediaSessionManager: MediaSessionManager get() = context.getSystemService(MediaSessionManager::class.java) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt index 10daa675ce36..e67fc97dad2e 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt @@ -17,19 +17,19 @@ package com.android.wm.shell.flicker.helpers import android.app.Instrumentation -import android.content.ComponentName import android.graphics.Region import android.os.SystemClock import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.wm.shell.flicker.testapp.Components class SplitScreenHelper( instrumentation: Instrumentation, activityLabel: String, - componentName: ComponentName + componentsInfo: Components.ComponentsInfo ) : BaseAppHelper( instrumentation, activityLabel, - componentName + componentsInfo ) { /** diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt new file mode 100644 index 000000000000..2015f4941cea --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AppTestBase.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.pip + +import android.app.ActivityTaskManager +import android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT +import android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS +import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD +import android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED +import android.os.SystemClock +import com.android.wm.shell.flicker.NonRotationTestBase + +abstract class AppTestBase( + rotationName: String, + rotation: Int +) : NonRotationTestBase(rotationName, rotation) { + companion object { + fun removeAllTasksButHome() { + val ALL_ACTIVITY_TYPE_BUT_HOME = intArrayOf( + ACTIVITY_TYPE_STANDARD, ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, + ACTIVITY_TYPE_UNDEFINED) + val atm = ActivityTaskManager.getService() + atm.removeRootTasksWithActivityTypes(ALL_ACTIVITY_TYPE_BUT_HOME) + } + + fun waitForAnimationComplete() { + // TODO: UiDevice doesn't have reliable way to wait for the completion of animation. + // Consider to introduce WindowManagerStateHelper to access Activity state. + SystemClock.sleep(1000) + } + } +} 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 new file mode 100644 index 000000000000..0663eb344f46 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterExitPipTest.kt @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.pip + +import android.view.Surface +import androidx.test.filters.RequiresDevice +import com.android.server.wm.flicker.dsl.runFlicker +import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen +import com.android.wm.shell.flicker.helpers.FixedAppHelper +import com.android.wm.shell.flicker.helpers.PipAppHelper +import com.android.wm.shell.flicker.navBarLayerIsAlwaysVisible +import com.android.wm.shell.flicker.navBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.statusBarLayerIsAlwaysVisible +import com.android.wm.shell.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test Pip launch and exit. + * To run this test: `atest WMShellFlickerTests:EnterExitPipTest` + */ +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class EnterExitPipTest( + rotationName: String, + rotation: Int +) : AppTestBase(rotationName, rotation) { + private val pipApp = PipAppHelper(instrumentation) + private val testApp = FixedAppHelper(instrumentation) + + @Test + fun testDisplayMetricsPinUnpin() { + runFlicker(instrumentation) { + withTestName { "testDisplayMetricsPinUnpin" } + setup { + test { + removeAllTasksButHome() + device.wakeUpAndGoToHomeScreen() + pipApp.launchViaIntent(stringExtras = mapOf(EXTRA_ENTER_PIP to "true")) + testApp.launchViaIntent() + waitForAnimationComplete() + } + } + transitions { + // This will bring PipApp to fullscreen + pipApp.launchViaIntent() + waitForAnimationComplete() + } + teardown { + test { + removeAllTasksButHome() + } + } + assertions { + val displayBounds = WindowUtils.getDisplayBounds(rotation) + windowManagerTrace { + all("pipApp must remain inside visible bounds") { + coversAtMostRegion(pipApp.defaultWindowName, displayBounds) + } + all("Initially shows both app windows then pipApp hides testApp") { + showsAppWindow(testApp.defaultWindowName) + .and().showsAppWindowOnTop(pipApp.defaultWindowName) + .then() + .hidesAppWindow(testApp.defaultWindowName) + } + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + } + layersTrace { + all("Initially shows both app layers then pipApp hides testApp") { + showsLayer(testApp.defaultWindowName) + .and().showsLayer(pipApp.defaultWindowName) + .then() + .hidesLayer(testApp.defaultWindowName) + } + start("testApp covers the fullscreen, pipApp remains inside display") { + hasVisibleRegion(testApp.defaultWindowName, displayBounds) + coversAtMostRegion(displayBounds, pipApp.defaultWindowName) + } + end("pipApp covers the fullscreen") { + hasVisibleRegion(pipApp.defaultWindowName, displayBounds) + } + navBarLayerIsAlwaysVisible() + statusBarLayerIsAlwaysVisible() + } + } + } + } + + companion object { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val supportedRotations = intArrayOf(Surface.ROTATION_0) + return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } + } + } +}
\ No newline at end of file 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 abb8fc52abbb..6c4e65818e49 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,28 +16,21 @@ package com.android.wm.shell.flicker.pip -import android.content.ComponentName -import android.graphics.Region -import android.util.Log import android.view.Surface -import android.view.WindowManager import androidx.test.filters.RequiresDevice -import com.android.compatibility.common.util.SystemUtil import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.dsl.runWithFlicker +import com.android.server.wm.flicker.helpers.WindowUtils import com.android.server.wm.flicker.helpers.closePipWindow import com.android.server.wm.flicker.helpers.hasPipWindow import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.wm.shell.flicker.TEST_APP_IME_ACTIVITY_COMPONENT_NAME import com.android.wm.shell.flicker.IME_WINDOW_NAME -import com.android.wm.shell.flicker.TEST_APP_PIP_ACTIVITY_WINDOW_NAME import com.android.wm.shell.flicker.helpers.ImeAppHelper import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.junit.runners.Parameterized -import java.io.IOException /** * Test Pip launch. @@ -50,9 +43,6 @@ class PipKeyboardTest( rotationName: String, rotation: Int ) : PipTestBase(rotationName, rotation) { - private val windowManager: WindowManager = - instrumentation.context.getSystemService(WindowManager::class.java) - private val keyboardApp = ImeAppHelper(instrumentation) private val keyboardScenario: FlickerBuilder @@ -71,7 +61,7 @@ class PipKeyboardTest( // open an app with an input field and a keyboard // UiAutomator doesn't support to launch the multiple Activities in a task. // So use launchActivity() for the Keyboard Activity. - launchActivity(TEST_APP_IME_ACTIVITY_COMPONENT_NAME) + keyboardApp.launchViaIntent() } } teardown { @@ -103,10 +93,8 @@ class PipKeyboardTest( assertions { windowManagerTrace { all("PiP window must remain inside visible bounds") { - coversAtMostRegion( - partialWindowTitle = "PipActivity", - region = Region(windowManager.maximumWindowMetrics.bounds) - ) + val displayBounds = WindowUtils.getDisplayBounds(rotation) + coversAtMostRegion(testApp.defaultWindowName, displayBounds) } } } @@ -132,74 +120,13 @@ class PipKeyboardTest( assertions { windowManagerTrace { end { - isAboveWindow(IME_WINDOW_NAME, TEST_APP_PIP_ACTIVITY_WINDOW_NAME) + isAboveWindow(IME_WINDOW_NAME, testApp.defaultWindowName) } } } } } - private fun launchActivity( - activity: ComponentName? = null, - action: String? = null, - flags: Set<Int> = setOf(), - boolExtras: Map<String, Boolean> = mapOf(), - intExtras: Map<String, Int> = mapOf(), - stringExtras: Map<String, String> = mapOf() - ) { - require(activity != null || !action.isNullOrBlank()) { - "Cannot launch an activity with neither activity name nor action!" - } - val command = composeCommand( - "start", activity, action, flags, boolExtras, intExtras, stringExtras) - executeShellCommand(command) - } - - private fun composeCommand( - command: String, - activity: ComponentName?, - action: String?, - flags: Set<Int>, - boolExtras: Map<String, Boolean>, - intExtras: Map<String, Int>, - stringExtras: Map<String, String> - ): String = buildString { - append("am ") - append(command) - activity?.let { - append(" -n ") - append(it.flattenToShortString()) - } - action?.let { - append(" -a ") - append(it) - } - flags.forEach { - append(" -f ") - append(it) - } - boolExtras.forEach { - append(it.withFlag("ez")) - } - intExtras.forEach { - append(it.withFlag("ei")) - } - stringExtras.forEach { - append(it.withFlag("es")) - } - } - - private fun Map.Entry<String, *>.withFlag(flag: String): String = " --$flag $key $value" - - private fun executeShellCommand(cmd: String): String { - try { - return SystemUtil.runShellCommand(instrumentation, cmd) - } catch (e: IOException) { - Log.e("FlickerTests", "Error running shell command: $cmd") - throw e - } - } - companion object { private const val TEST_REPETITIONS = 10 diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipOrientationTest.kt new file mode 100644 index 000000000000..322034ce7688 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipOrientationTest.kt @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.pip + +import android.content.Intent +import android.view.Surface +import androidx.test.filters.RequiresDevice +import com.android.server.wm.flicker.dsl.runFlicker +import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen +import com.android.wm.shell.flicker.helpers.FixedAppHelper +import com.android.wm.shell.flicker.helpers.PipAppHelper +import com.android.wm.shell.flicker.navBarLayerIsAlwaysVisible +import com.android.wm.shell.flicker.navBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.statusBarLayerIsAlwaysVisible +import com.android.wm.shell.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP +import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_SET_REQUESTED_ORIENTATION +import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP +import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_PIP_ORIENTATION +import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION +import org.junit.Assert.assertEquals +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test Pip with orientation changes. + * To run this test: `atest WMShellFlickerTests:PipOrientationTest` + */ +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class PipOrientationTest( + rotationName: String, + rotation: Int +) : AppTestBase(rotationName, rotation) { + // Helper class to process test actions by broadcast. + private inner class BroadcastActionTrigger { + private fun createIntentWithAction(broadcastAction: String): Intent { + return Intent(broadcastAction).setFlags(Intent.FLAG_RECEIVER_FOREGROUND) + } + fun doAction(broadcastAction: String) { + instrumentation.getContext().sendBroadcast(createIntentWithAction(broadcastAction)) + } + fun requestOrientationForPip(orientation: Int) { + instrumentation.getContext() + .sendBroadcast(createIntentWithAction(ACTION_SET_REQUESTED_ORIENTATION) + .putExtra(EXTRA_PIP_ORIENTATION, orientation.toString())) + } + } + private val broadcastActionTrigger = BroadcastActionTrigger() + + // Corresponds to ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + private val ORIENTATION_LANDSCAPE = 0 + // Corresponds to ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + private val ORIENTATION_PORTRAIT = 1 + + private val testApp = FixedAppHelper(instrumentation) + private val pipApp = PipAppHelper(instrumentation) + + @Test + fun testEnterPipToOtherOrientation() { + runFlicker(instrumentation) { + withTestName { "testEnterPipToOtherOrientation" } + setup { + test { + removeAllTasksButHome() + device.wakeUpAndGoToHomeScreen() + // Launch a portrait only app on the fullscreen stack + testApp.launchViaIntent(stringExtras = mapOf( + EXTRA_FIXED_ORIENTATION to ORIENTATION_PORTRAIT.toString())) + waitForAnimationComplete() + // Launch the PiP activity fixed as landscape + pipApp.launchViaIntent(stringExtras = mapOf( + EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString())) + waitForAnimationComplete() + } + } + transitions { + // Enter PiP, and assert that the PiP is within bounds now that the device is back + // in portrait + broadcastActionTrigger.doAction(ACTION_ENTER_PIP) + waitForAnimationComplete() + } + teardown { + test { + removeAllTasksButHome() + } + } + assertions { + windowManagerTrace { + all("pipApp window is always on top") { + showsAppWindowOnTop(pipApp.defaultWindowName) + } + start("pipApp window hides testApp") { + hidesAppWindow(testApp.defaultWindowName) + } + end("testApp windows is shown") { + showsAppWindow(testApp.defaultWindowName) + } + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + } + layersTrace { + val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90) + val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0) + start("pipApp layer hides testApp") { + hasVisibleRegion(pipApp.defaultWindowName, startingBounds) + hidesLayer(testApp.defaultWindowName) + } + end("testApp layer covers fullscreen") { + hasVisibleRegion(testApp.defaultWindowName, endingBounds) + } + navBarLayerIsAlwaysVisible(bugId = 140855415) + statusBarLayerIsAlwaysVisible(bugId = 140855415) + } + } + } + } + + @Test + fun testSetRequestedOrientationWhilePinned() { + runFlicker(instrumentation) { + withTestName { "testSetRequestedOrientationWhilePinned" } + setup { + test { + removeAllTasksButHome() + device.wakeUpAndGoToHomeScreen() + // Launch the PiP activity fixed as landscape + pipApp.launchViaIntent(stringExtras = mapOf( + EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString(), + EXTRA_ENTER_PIP to "true")) + waitForAnimationComplete() + assertEquals(Surface.ROTATION_0, device.displayRotation) + } + } + transitions { + // Request that the orientation is set to landscape + broadcastActionTrigger.requestOrientationForPip(ORIENTATION_LANDSCAPE) + + // Launch the activity back into fullscreen and ensure that it is now in landscape + pipApp.launchViaIntent() + waitForAnimationComplete() + assertEquals(Surface.ROTATION_90, device.displayRotation) + } + teardown { + test { + removeAllTasksButHome() + } + } + assertions { + val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0) + val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90) + windowManagerTrace { + start("PIP window must remain inside display") { + coversAtMostRegion(pipApp.defaultWindowName, startingBounds) + } + end("pipApp shows on top") { + showsAppWindowOnTop(pipApp.defaultWindowName) + } + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + } + layersTrace { + start("PIP layer must remain inside display") { + coversAtMostRegion(startingBounds, pipApp.defaultWindowName) + } + end("pipApp layer covers fullscreen") { + hasVisibleRegion(pipApp.defaultWindowName, endingBounds) + } + navBarLayerIsAlwaysVisible(bugId = 140855415) + statusBarLayerIsAlwaysVisible(bugId = 140855415) + } + } + } + } + + companion object { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val supportedRotations = intArrayOf(Surface.ROTATION_0) + return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } + } + } +}
\ No newline at end of file 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 new file mode 100644 index 000000000000..96d98d56e069 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.pip + +import android.view.Surface +import androidx.test.filters.RequiresDevice +import androidx.test.platform.app.InstrumentationRegistry +import com.android.server.wm.flicker.Flicker +import com.android.server.wm.flicker.FlickerTestRunner +import com.android.server.wm.flicker.FlickerTestRunnerFactory +import com.android.server.wm.flicker.endRotation +import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.server.wm.flicker.helpers.buildTestTag +import com.android.server.wm.flicker.helpers.setRotation +import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen +import com.android.server.wm.flicker.repetitions +import com.android.server.wm.flicker.startRotation +import com.android.wm.shell.flicker.helpers.FixedAppHelper +import com.android.wm.shell.flicker.helpers.PipAppHelper +import com.android.wm.shell.flicker.navBarLayerIsAlwaysVisible +import com.android.wm.shell.flicker.navBarLayerRotatesAndScales +import com.android.wm.shell.flicker.navBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.noUncoveredRegions +import com.android.wm.shell.flicker.statusBarLayerIsAlwaysVisible +import com.android.wm.shell.flicker.statusBarLayerRotatesScales +import com.android.wm.shell.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP +import org.junit.FixMethodOrder +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test Pip Stack in bounds after rotations. + * To run this test: `atest WMShellFlickerTests:PipRotationTest` + */ +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class PipRotationTest( + testName: String, + flickerSpec: Flicker +) : FlickerTestRunner(testName, flickerSpec) { + companion object { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val instrumentation = InstrumentationRegistry.getInstrumentation() + val testApp = FixedAppHelper(instrumentation) + val pipApp = PipAppHelper(instrumentation) + return FlickerTestRunnerFactory(instrumentation, + listOf(Surface.ROTATION_0, Surface.ROTATION_90)) + .buildRotationTest { configuration -> + withTestName { buildTestTag("PipRotationTest", testApp, configuration) } + repeat { configuration.repetitions } + setup { + test { + AppTestBase.removeAllTasksButHome() + device.wakeUpAndGoToHomeScreen() + pipApp.launchViaIntent(stringExtras = mapOf( + EXTRA_ENTER_PIP to "true")) + testApp.launchViaIntent() + AppTestBase.waitForAnimationComplete() + } + eachRun { + setRotation(configuration.startRotation) + } + } + transitions { + setRotation(configuration.endRotation) + } + teardown { + eachRun { + setRotation(Surface.ROTATION_0) + } + test { + AppTestBase.removeAllTasksButHome() + } + } + assertions { + windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + } + layersTrace { + navBarLayerIsAlwaysVisible(bugId = 140855415) + statusBarLayerIsAlwaysVisible(bugId = 140855415) + noUncoveredRegions(configuration.startRotation, + configuration.endRotation, allStates = false) + navBarLayerRotatesAndScales(configuration.startRotation, + configuration.endRotation) + statusBarLayerRotatesScales(configuration.startRotation, + configuration.endRotation) + } + layersTrace { + val startingBounds = WindowUtils.getDisplayBounds( + configuration.startRotation) + val endingBounds = WindowUtils.getDisplayBounds( + configuration.endRotation) + start("appLayerRotates_StartingBounds") { + hasVisibleRegion(testApp.defaultWindowName, startingBounds) + coversAtMostRegion(startingBounds, pipApp.defaultWindowName) + } + end("appLayerRotates_EndingBounds") { + hasVisibleRegion(testApp.defaultWindowName, endingBounds) + coversAtMostRegion(endingBounds, pipApp.defaultWindowName) + } + } + } + } + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt new file mode 100644 index 000000000000..d20552f0739d --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.pip + +import android.view.Surface +import androidx.test.filters.FlakyTest +import androidx.test.filters.RequiresDevice +import com.android.server.wm.flicker.dsl.runFlicker +import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.server.wm.flicker.helpers.exitSplitScreen +import com.android.server.wm.flicker.helpers.isInSplitScreen +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen +import com.android.wm.shell.flicker.helpers.ImeAppHelper +import com.android.wm.shell.flicker.helpers.FixedAppHelper +import com.android.wm.shell.flicker.helpers.PipAppHelper +import com.android.wm.shell.flicker.navBarLayerIsAlwaysVisible +import com.android.wm.shell.flicker.navBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.statusBarLayerIsAlwaysVisible +import com.android.wm.shell.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test Pip with split-screen. + * To run this test: `atest WMShellFlickerTests:PipSplitScreenTest` + */ +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@FlakyTest(bugId = 161435597) +class PipSplitScreenTest( + rotationName: String, + rotation: Int +) : AppTestBase(rotationName, rotation) { + private val pipApp = PipAppHelper(instrumentation) + private val imeApp = ImeAppHelper(instrumentation) + private val testApp = FixedAppHelper(instrumentation) + + @Test + fun testShowsPipLaunchingToSplitScreen() { + runFlicker(instrumentation) { + withTestName { "testShowsPipLaunchingToSplitScreen" } + repeat { TEST_REPETITIONS } + setup { + test { + removeAllTasksButHome() + device.wakeUpAndGoToHomeScreen() + pipApp.launchViaIntent(stringExtras = mapOf(EXTRA_ENTER_PIP to "true")) + waitForAnimationComplete() + } + } + transitions { + testApp.launchViaIntent() + device.launchSplitScreen() + imeApp.launchViaIntent() + waitForAnimationComplete() + } + teardown { + eachRun { + imeApp.exit() + if (device.isInSplitScreen()) { + device.exitSplitScreen() + } + testApp.exit() + } + test { + removeAllTasksButHome() + } + } + assertions { + val displayBounds = WindowUtils.getDisplayBounds(rotation) + windowManagerTrace { + all("PIP window must remain inside visible bounds") { + coversAtMostRegion(pipApp.defaultWindowName, displayBounds) + } + end("Both app windows should be visible") { + showsAppWindow(testApp.defaultWindowName) + showsAppWindow(imeApp.defaultWindowName) + noWindowsOverlap(testApp.defaultWindowName, imeApp.defaultWindowName) + } + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + } + layersTrace { + all("PIP layer must remain inside visible bounds") { + coversAtMostRegion(displayBounds, pipApp.defaultWindowName) + } + end("Both app layers should be visible") { + coversAtMostRegion(displayBounds, testApp.defaultWindowName) + coversAtMostRegion(displayBounds, imeApp.defaultWindowName) + } + navBarLayerIsAlwaysVisible() + statusBarLayerIsAlwaysVisible() + } + } + } + } + + companion object { + const val TEST_REPETITIONS = 2 + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val supportedRotations = intArrayOf(Surface.ROTATION_0) + return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt index c1c34ecfbaec..03a92119fc86 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTestBase.kt @@ -16,12 +16,11 @@ package com.android.wm.shell.flicker.pip -import com.android.wm.shell.flicker.NonRotationTestBase import com.android.wm.shell.flicker.helpers.PipAppHelper abstract class PipTestBase( rotationName: String, rotation: Int -) : NonRotationTestBase(rotationName, rotation) { +) : AppTestBase(rotationName, rotation) { protected val testApp = PipAppHelper(instrumentation) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt index 496fe94ba951..a3440df9ddf8 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt @@ -17,11 +17,10 @@ package com.android.wm.shell.flicker.splitscreen import com.android.wm.shell.flicker.NonRotationTestBase -import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_COMPONENT_NAME import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL -import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_COMPONENT_NAME import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import com.android.wm.shell.flicker.testapp.Components abstract class SplitScreenTestBase( rotationName: String, @@ -29,8 +28,8 @@ abstract class SplitScreenTestBase( ) : NonRotationTestBase(rotationName, rotation) { protected val splitScreenApp = SplitScreenHelper(instrumentation, TEST_APP_SPLITSCREEN_PRIMARY_LABEL, - TEST_APP_SPLITSCREEN_PRIMARY_COMPONENT_NAME) + Components.SplitScreenActivity()) protected val secondaryApp = SplitScreenHelper(instrumentation, TEST_APP_SPLITSCREEN_SECONDARY_LABEL, - TEST_APP_SPLITSCREEN_SECONDARY_COMPONENT_NAME) + Components.SplitScreenSecondaryActivity()) } 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 d12b49245277..26627a47ee62 100644 --- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/Android.bp @@ -18,3 +18,9 @@ android_test { sdk_version: "current", test_suites: ["device-tests"], } + +java_library { + 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/flicker/test-apps/flickerapp/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml index 628926a97bf5..a583b725899b 100644 --- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml @@ -21,13 +21,25 @@ android:targetSdkVersion="29"/> <application android:allowBackup="false" android:supportsRtl="true"> + <activity android:name=".FixedActivity" + android:resizeableActivity="true" + android:supportsPictureInPicture="true" + android:launchMode="singleTop" + android:label="FixedApp" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> <activity android:name=".PipActivity" - android:resizeableActivity="true" - android:supportsPictureInPicture="true" - android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" - android:taskAffinity="com.android.wm.shell.flicker.testapp.PipActivity" - android:label="PipApp" - android:exported="true"> + android:resizeableActivity="true" + android:supportsPictureInPicture="true" + android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" + android:taskAffinity="com.android.wm.shell.flicker.testapp.PipActivity" + android:launchMode="singleTop" + android:label="PipApp" + android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> @@ -39,9 +51,9 @@ </activity> <activity android:name=".ImeActivity" - android:taskAffinity="com.android.wm.shell.flicker.testapp.ImeActivity" - android:label="ImeApp" - android:exported="true"> + android:taskAffinity="com.android.wm.shell.flicker.testapp.ImeActivity" + android:label="ImeApp" + android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java new file mode 100644 index 000000000000..8e9b4cb2d53e --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.testapp; + +import android.content.ComponentName; + +public class Components { + public abstract static class ComponentsInfo { + public ComponentName getComponentName() { + return ComponentName.createRelative(PACKAGE_NAME, "." + getActivityName()); + } + public abstract String getActivityName(); + } + + public static final String PACKAGE_NAME = "com.android.wm.shell.flicker.testapp"; + + public static class FixedActivity extends ComponentsInfo { + // Sets the fixed orientation (can be one of {@link ActivityInfo.ScreenOrientation} + public static final String EXTRA_FIXED_ORIENTATION = "fixed_orientation"; + + @Override + public String getActivityName() { + return FixedActivity.class.getSimpleName(); + } + } + + public static class PipActivity extends ComponentsInfo { + // Intent action that this activity dynamically registers to enter picture-in-picture + public static final String ACTION_ENTER_PIP = PACKAGE_NAME + ".PipActivity.ENTER_PIP"; + // Intent action that this activity dynamically registers to set requested orientation. + // Will apply the oriention to the value set in the EXTRA_FIXED_ORIENTATION extra. + public static final String ACTION_SET_REQUESTED_ORIENTATION = + PACKAGE_NAME + ".PipActivity.SET_REQUESTED_ORIENTATION"; + + // Calls enterPictureInPicture() on creation + public static final String EXTRA_ENTER_PIP = "enter_pip"; + // Sets the fixed orientation (can be one of {@link ActivityInfo.ScreenOrientation} + public static final String EXTRA_PIP_ORIENTATION = "fixed_orientation"; + // Adds a click listener to finish this activity when it is clicked + public static final String EXTRA_TAP_TO_FINISH = "tap_to_finish"; + + @Override + public String getActivityName() { + return PipActivity.class.getSimpleName(); + } + } + + public static class ImeActivity extends ComponentsInfo { + @Override + public String getActivityName() { + return ImeActivity.class.getSimpleName(); + } + } + + public static class SplitScreenActivity extends ComponentsInfo { + @Override + public String getActivityName() { + return SplitScreenActivity.class.getSimpleName(); + } + } + + public static class SplitScreenSecondaryActivity extends ComponentsInfo { + @Override + public String getActivityName() { + return SplitScreenSecondaryActivity.class.getSimpleName(); + } + } +} diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/FixedActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/FixedActivity.java new file mode 100644 index 000000000000..d4ae6c1313bf --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/FixedActivity.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.testapp; + +import static com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION; + +import android.os.Bundle; + +public class FixedActivity extends SimpleActivity { + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + // Set the fixed orientation if requested + if (getIntent().hasExtra(EXTRA_FIXED_ORIENTATION)) { + final int ori = Integer.parseInt(getIntent().getStringExtra(EXTRA_FIXED_ORIENTATION)); + setRequestedOrientation(ori); + } + } +} diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java index 909219583bf7..a6ba7823e22d 100644 --- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/PipActivity.java @@ -24,6 +24,11 @@ import static android.media.session.PlaybackState.STATE_PAUSED; import static android.media.session.PlaybackState.STATE_PLAYING; import static android.media.session.PlaybackState.STATE_STOPPED; +import static com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP; +import static com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_SET_REQUESTED_ORIENTATION; +import static com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP; +import static com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_PIP_ORIENTATION; + import android.app.Activity; import android.app.PendingIntent; import android.app.PictureInPictureParams; @@ -32,12 +37,12 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Configuration; import android.graphics.drawable.Icon; import android.media.MediaMetadata; import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Bundle; +import android.util.Log; import android.util.Rational; import android.view.View; import android.view.Window; @@ -50,6 +55,7 @@ import java.util.Collections; import java.util.List; public class PipActivity extends Activity { + private static final String TAG = PipActivity.class.getSimpleName(); /** * A media session title for when the session is in {@link STATE_PLAYING}. * TvPipNotificationTests check whether the actual notification title matches this string. @@ -88,27 +94,43 @@ public class PipActivity extends Activity { private final List<RemoteAction> mSwitchOffActions = new ArrayList<>(); private final List<RemoteAction> mSwitchOnActions = new ArrayList<>(); - private final BroadcastReceiver mCustomActionReceiver = new BroadcastReceiver() { + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - switch (intent.getAction()) { - case ACTION_SWITCH_ON: - mPipParamsBuilder.setActions(mSwitchOnActions); - break; - case ACTION_SWITCH_OFF: - mPipParamsBuilder.setActions(mSwitchOffActions); - break; - case ACTION_CLEAR: - mPipParamsBuilder.setActions(Collections.emptyList()); - break; - case ACTION_NO_OP: - default: - return; + if (isInPictureInPictureMode()) { + switch (intent.getAction()) { + case ACTION_SWITCH_ON: + mPipParamsBuilder.setActions(mSwitchOnActions); + break; + case ACTION_SWITCH_OFF: + mPipParamsBuilder.setActions(mSwitchOffActions); + break; + case ACTION_CLEAR: + mPipParamsBuilder.setActions(Collections.emptyList()); + break; + case ACTION_NO_OP: + return; + default: + Log.w(TAG, "Unhandled action=" + intent.getAction()); + return; + } + setPictureInPictureParams(mPipParamsBuilder.build()); + } else { + switch (intent.getAction()) { + case ACTION_ENTER_PIP: + enterPip(null); + break; + case ACTION_SET_REQUESTED_ORIENTATION: + setRequestedOrientation(Integer.parseInt(intent.getStringExtra( + EXTRA_PIP_ORIENTATION))); + break; + default: + Log.w(TAG, "Unhandled action=" + intent.getAction()); + return; + } } - setPictureInPictureParams(mPipParamsBuilder.build()); } }; - private boolean mIsReceiverRegistered = false; @Override public void onCreate(Bundle savedInstanceState) { @@ -160,36 +182,25 @@ public class PipActivity extends Activity { final RemoteAction clearAllAction = buildRemoteAction(icon, PIP_ACTION_CLEAR, ACTION_CLEAR); mSwitchOffActions.addAll(Arrays.asList(switchOnAction, clearAllAction)); mSwitchOnActions.addAll(Arrays.asList(noOpAction, switchOffAction, clearAllAction)); + + final IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_NO_OP); + filter.addAction(ACTION_SWITCH_ON); + filter.addAction(ACTION_SWITCH_OFF); + filter.addAction(ACTION_CLEAR); + filter.addAction(ACTION_SET_REQUESTED_ORIENTATION); + filter.addAction(ACTION_ENTER_PIP); + registerReceiver(mBroadcastReceiver, filter); + + handleIntentExtra(getIntent()); } @Override protected void onDestroy() { - if (mIsReceiverRegistered) { - unregisterReceiver(mCustomActionReceiver); - mIsReceiverRegistered = false; - } + unregisterReceiver(mBroadcastReceiver); super.onDestroy(); } - @Override - public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, - Configuration newConfig) { - if (isInPictureInPictureMode && !mIsReceiverRegistered) { - final IntentFilter filter = new IntentFilter(); - filter.addAction(ACTION_NO_OP); - filter.addAction(ACTION_SWITCH_ON); - filter.addAction(ACTION_SWITCH_OFF); - filter.addAction(ACTION_CLEAR); - registerReceiver(mCustomActionReceiver, filter); - - mIsReceiverRegistered = true; - } else if (!isInPictureInPictureMode && mIsReceiverRegistered) { - unregisterReceiver(mCustomActionReceiver); - - mIsReceiverRegistered = false; - } - } - private RemoteAction buildRemoteAction(Icon icon, String label, String action) { final Intent intent = new Intent(action); final PendingIntent pendingIntent = @@ -254,4 +265,17 @@ public class PipActivity extends Activity { mMediaSession.setMetadata(mMediaMetadataBuilder.build()); mMediaSession.setActive(newState != STATE_STOPPED); } + + private void handleIntentExtra(Intent intent) { + // Set the fixed orientation if requested + if (intent.hasExtra(EXTRA_PIP_ORIENTATION)) { + final int ori = Integer.parseInt(getIntent().getStringExtra(EXTRA_PIP_ORIENTATION)); + setRequestedOrientation(ori); + } + // Enter picture in picture with the given aspect ratio if provided + if (intent.hasExtra(EXTRA_ENTER_PIP)) { + mPipParamsBuilder.setActions(mSwitchOnActions); + enterPip(null); + } + } } diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in index 49817925d9b4..c6c4ba8a6493 100644 --- a/libs/hwui/DisplayListOps.in +++ b/libs/hwui/DisplayListOps.in @@ -19,7 +19,6 @@ X(Save) X(Restore) X(SaveLayer) X(SaveBehind) -X(Concat44) X(Concat) X(SetMatrix) X(Scale) diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 473dc53dc4bf..a495ec4ac411 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -125,24 +125,18 @@ struct SaveBehind final : Op { } }; -struct Concat44 final : Op { - static const auto kType = Type::Concat44; - Concat44(const SkM44& m) : matrix(m) {} - SkM44 matrix; - void draw(SkCanvas* c, const SkMatrix&) const { c->concat(matrix); } -}; struct Concat final : Op { static const auto kType = Type::Concat; - Concat(const SkMatrix& matrix) : matrix(matrix) {} - SkMatrix matrix; + Concat(const SkM44& matrix) : matrix(matrix) {} + SkM44 matrix; void draw(SkCanvas* c, const SkMatrix&) const { c->concat(matrix); } }; struct SetMatrix final : Op { static const auto kType = Type::SetMatrix; - SetMatrix(const SkMatrix& matrix) : matrix(matrix) {} - SkMatrix matrix; + SetMatrix(const SkM44& matrix) : matrix(matrix) {} + SkM44 matrix; void draw(SkCanvas* c, const SkMatrix& original) const { - c->setMatrix(SkMatrix::Concat(original, matrix)); + c->setMatrix(SkM44(original) * matrix); } }; struct Scale final : Op { @@ -569,12 +563,9 @@ void DisplayListData::saveBehind(const SkRect* subset) { } void DisplayListData::concat(const SkM44& m) { - this->push<Concat44>(0, m); -} -void DisplayListData::concat(const SkMatrix& matrix) { - this->push<Concat>(0, matrix); + this->push<Concat>(0, m); } -void DisplayListData::setMatrix(const SkMatrix& matrix) { +void DisplayListData::setMatrix(const SkM44& matrix) { this->push<SetMatrix>(0, matrix); } void DisplayListData::scale(SkScalar sx, SkScalar sy) { @@ -834,10 +825,7 @@ bool RecordingCanvas::onDoSaveBehind(const SkRect* subset) { void RecordingCanvas::didConcat44(const SkM44& m) { fDL->concat(m); } -void RecordingCanvas::didConcat(const SkMatrix& matrix) { - fDL->concat(matrix); -} -void RecordingCanvas::didSetMatrix(const SkMatrix& matrix) { +void RecordingCanvas::didSetM44(const SkM44& matrix) { fDL->setMatrix(matrix); } void RecordingCanvas::didScale(SkScalar sx, SkScalar sy) { diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index 63d120c4ca19..4851148cd4d8 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -82,8 +82,7 @@ private: void restore(); void concat(const SkM44&); - void concat(const SkMatrix&); - void setMatrix(const SkMatrix&); + void setMatrix(const SkM44&); void scale(SkScalar, SkScalar); void translate(SkScalar, SkScalar); void translateZ(SkScalar); @@ -154,8 +153,7 @@ public: void onFlush() override; void didConcat44(const SkM44&) override; - void didConcat(const SkMatrix&) override; - void didSetMatrix(const SkMatrix&) override; + void didSetM44(const SkM44&) override; void didScale(SkScalar, SkScalar) override; void didTranslate(SkScalar, SkScalar) override; diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp index 68541b4b31f0..671c66f11e32 100644 --- a/libs/hwui/WebViewFunctorManager.cpp +++ b/libs/hwui/WebViewFunctorManager.cpp @@ -26,6 +26,35 @@ namespace android::uirenderer { +namespace { +class ScopedCurrentFunctor { +public: + ScopedCurrentFunctor(WebViewFunctor* functor) { + ALOG_ASSERT(!sCurrentFunctor); + ALOG_ASSERT(functor); + sCurrentFunctor = functor; + } + ~ScopedCurrentFunctor() { + ALOG_ASSERT(sCurrentFunctor); + sCurrentFunctor = nullptr; + } + + static ASurfaceControl* getSurfaceControl() { + ALOG_ASSERT(sCurrentFunctor); + return sCurrentFunctor->getSurfaceControl(); + } + static void mergeTransaction(ASurfaceTransaction* transaction) { + ALOG_ASSERT(sCurrentFunctor); + sCurrentFunctor->mergeTransaction(transaction); + } + +private: + static WebViewFunctor* sCurrentFunctor; +}; + +WebViewFunctor* ScopedCurrentFunctor::sCurrentFunctor = nullptr; +} // namespace + RenderMode WebViewFunctor_queryPlatformRenderMode() { auto pipelineType = Properties::getRenderPipelineType(); switch (pipelineType) { @@ -83,7 +112,15 @@ void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) { if (!mHasContext) { mHasContext = true; } - mCallbacks.gles.draw(mFunctor, mData, drawInfo); + ScopedCurrentFunctor currentFunctor(this); + + WebViewOverlayData overlayParams = { + // TODO: + .overlaysMode = OverlaysMode::Disabled, + .getSurfaceControl = currentFunctor.getSurfaceControl, + .mergeTransaction = currentFunctor.mergeTransaction, + }; + mCallbacks.gles.draw(mFunctor, mData, drawInfo, overlayParams); } void WebViewFunctor::initVk(const VkFunctorInitParams& params) { @@ -98,7 +135,15 @@ void WebViewFunctor::initVk(const VkFunctorInitParams& params) { void WebViewFunctor::drawVk(const VkFunctorDrawParams& params) { ATRACE_NAME("WebViewFunctor::drawVk"); - mCallbacks.vk.draw(mFunctor, mData, params); + ScopedCurrentFunctor currentFunctor(this); + + WebViewOverlayData overlayParams = { + // TODO + .overlaysMode = OverlaysMode::Disabled, + .getSurfaceControl = currentFunctor.getSurfaceControl, + .mergeTransaction = currentFunctor.mergeTransaction, + }; + mCallbacks.vk.draw(mFunctor, mData, params, overlayParams); } void WebViewFunctor::postDrawVk() { @@ -118,6 +163,20 @@ void WebViewFunctor::destroyContext() { } } +void WebViewFunctor::removeOverlays() { + ScopedCurrentFunctor currentFunctor(this); + mCallbacks.removeOverlays(mFunctor, mData, currentFunctor.mergeTransaction); +} + +ASurfaceControl* WebViewFunctor::getSurfaceControl() { + // TODO + return nullptr; +} + +void WebViewFunctor::mergeTransaction(ASurfaceTransaction* transaction) { + // TODO +} + WebViewFunctorManager& WebViewFunctorManager::instance() { static WebViewFunctorManager sInstance; return sInstance; diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h index 675b738c6406..737d60525aa9 100644 --- a/libs/hwui/WebViewFunctorManager.h +++ b/libs/hwui/WebViewFunctorManager.h @@ -56,6 +56,8 @@ public: void postDrawVk() { mReference.postDrawVk(); } + void removeOverlays() { mReference.removeOverlays(); } + private: friend class WebViewFunctor; @@ -71,6 +73,10 @@ public: void drawVk(const VkFunctorDrawParams& params); void postDrawVk(); void destroyContext(); + void removeOverlays(); + + ASurfaceControl* getSurfaceControl(); + void mergeTransaction(ASurfaceTransaction* transaction); sp<Handle> createHandle() { LOG_ALWAYS_FATAL_IF(mCreatedHandle); diff --git a/libs/hwui/jni/pdf/PdfEditor.cpp b/libs/hwui/jni/pdf/PdfEditor.cpp index e65921ac8e0a..427bafa1bd83 100644 --- a/libs/hwui/jni/pdf/PdfEditor.cpp +++ b/libs/hwui/jni/pdf/PdfEditor.cpp @@ -129,8 +129,8 @@ static void nativeSetTransformAndClip(JNIEnv* env, jclass thiz, jlong documentPt // PDF's coordinate system origin is left-bottom while in graphics it // is the top-left. So, translate the PDF coordinates to ours. - SkMatrix reflectOnX = SkMatrix::MakeScale(1, -1); - SkMatrix moveUp = SkMatrix::MakeTrans(0, FPDF_GetPageHeight(page)); + SkMatrix reflectOnX = SkMatrix::Scale(1, -1); + SkMatrix moveUp = SkMatrix::Translate(0, FPDF_GetPageHeight(page)); SkMatrix coordinateChange = SkMatrix::Concat(moveUp, reflectOnX); // Apply the transformation what was created in our coordinates. diff --git a/libs/hwui/private/hwui/WebViewFunctor.h b/libs/hwui/private/hwui/WebViewFunctor.h index 96da947ace08..22ae59e5137b 100644 --- a/libs/hwui/private/hwui/WebViewFunctor.h +++ b/libs/hwui/private/hwui/WebViewFunctor.h @@ -17,6 +17,15 @@ #ifndef FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H #define FRAMEWORKS_BASE_WEBVIEWFUNCTOR_H +#ifdef __ANDROID__ // Layoutlib does not support surface control +#include <android/surface_control.h> +#else +// To avoid ifdefs around overlay implementation all over the place we typedef these to void *. They +// won't be used. +typedef void* ASurfaceControl; +typedef void* ASurfaceTransaction; +#endif + #include <cutils/compiler.h> #include <private/hwui/DrawGlInfo.h> #include <private/hwui/DrawVkInfo.h> @@ -28,6 +37,14 @@ enum class RenderMode { Vulkan, }; +enum class OverlaysMode { + // Indicated that webview should not promote anything to overlays this draw + // and remove all visible overlays. + Disabled, + // Indicates that webview can use overlays. + Enabled +}; + // Static for the lifetime of the process ANDROID_API RenderMode WebViewFunctor_queryPlatformRenderMode(); @@ -35,6 +52,23 @@ struct WebViewSyncData { bool applyForceDark; }; +struct WebViewOverlayData { + // Desired overlay mode for this draw. + OverlaysMode overlaysMode; + + // Returns parent ASurfaceControl for WebView overlays. It will be have same + // geometry as the surface we draw into and positioned below it (underlay). + // This does not pass ownership to webview, but guaranteed to be alive until + // transaction from next removeOverlays call or functor destruction will be + // finished. + ASurfaceControl* (*getSurfaceControl)(); + + // Merges WebView transaction to be applied synchronously with current draw. + // This doesn't pass ownership of the transaction, changes will be copied and + // webview can free transaction right after the call. + void (*mergeTransaction)(ASurfaceTransaction*); +}; + struct WebViewFunctorCallbacks { // kModeSync, called on RenderThread void (*onSync)(int functor, void* data, const WebViewSyncData& syncData); @@ -48,16 +82,23 @@ struct WebViewFunctorCallbacks { // this functor had ever been drawn. void (*onDestroyed)(int functor, void* data); + // Called on render thread to force webview hide all overlays and stop updating them. + // Should happen during hwui draw (e.g can be called instead of draw if webview + // isn't visible and won't receive draw) and support MergeTransaction call. + void (*removeOverlays)(int functor, void* data, void (*mergeTransaction)(ASurfaceTransaction*)); + union { struct { // Called on RenderThread. initialize is guaranteed to happen before this call - void (*draw)(int functor, void* data, const DrawGlInfo& params); + void (*draw)(int functor, void* data, const DrawGlInfo& params, + const WebViewOverlayData& overlayParams); } gles; struct { // Called either the first time the functor is used or the first time it's used after // a call to onContextDestroyed. void (*initialize)(int functor, void* data, const VkFunctorInitParams& params); - void (*draw)(int functor, void* data, const VkFunctorDrawParams& params); + void (*draw)(int functor, void* data, const VkFunctorDrawParams& params, + const WebViewOverlayData& overlayParams); void (*postDraw)(int functor, void*); } vk; }; diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h index 36c5a8c1b3de..c1d8b761514b 100644 --- a/libs/hwui/tests/common/TestUtils.h +++ b/libs/hwui/tests/common/TestUtils.h @@ -323,7 +323,8 @@ public: }; switch (mode) { case RenderMode::OpenGL_ES: - callbacks.gles.draw = [](int functor, void* client_data, const DrawGlInfo& params) { + callbacks.gles.draw = [](int functor, void* client_data, const DrawGlInfo& params, + const WebViewOverlayData& overlay_params) { expectOnRenderThread("draw"); sMockFunctorCounts[functor].glesDraw++; }; diff --git a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp index f4c3e13b0ea6..955a5e7d8b3a 100644 --- a/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp +++ b/libs/hwui/tests/unit/DeferredLayerUpdaterTests.cpp @@ -39,7 +39,7 @@ RENDERTHREAD_TEST(DeferredLayerUpdater, updateLayer) { EXPECT_EQ(Matrix4::identity(), layerUpdater->backingLayer()->getTexTransform()); // push the deferred updates to the layer - SkMatrix scaledMatrix = SkMatrix::MakeScale(0.5, 0.5); + SkMatrix scaledMatrix = SkMatrix::Scale(0.5, 0.5); SkBitmap bitmap; bitmap.allocN32Pixels(16, 16); sk_sp<SkImage> layerImage = SkImage::MakeFromBitmap(bitmap); diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp index abdf9d587189..26bc65915c7a 100644 --- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp @@ -206,7 +206,7 @@ TEST(RenderNodeDrawable, saveLayerClipAndMatrixRestore) { ASSERT_EQ(SkRect::MakeLTRB(50, 50, 350, 350), getRecorderClipBounds(recorder)); recorder.translate(300.0f, 400.0f); - EXPECT_EQ(SkMatrix::MakeTrans(300.0f, 400.0f), getRecorderMatrix(recorder)); + EXPECT_EQ(SkMatrix::Translate(300.0f, 400.0f), getRecorderMatrix(recorder)); recorder.restore(); ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder)); @@ -1107,27 +1107,27 @@ TEST(ReorderBarrierDrawable, testShadowMatrix) { EXPECT_EQ(dy, TRANSLATE_Y); } - virtual void didSetMatrix(const SkMatrix& matrix) override { + virtual void didSetM44(const SkM44& matrix) override { mDrawCounter++; // First invocation is EndReorderBarrierDrawable::drawShadow to apply shadow matrix. // Second invocation is preparing the matrix for an elevated RenderNodeDrawable. - EXPECT_TRUE(matrix.isIdentity()); + EXPECT_TRUE(matrix == SkM44()); EXPECT_TRUE(getTotalMatrix().isIdentity()); } - virtual void didConcat(const SkMatrix& matrix) override { + virtual void didConcat44(const SkM44& matrix) override { mDrawCounter++; if (mFirstDidConcat) { // First invocation is EndReorderBarrierDrawable::drawShadow to apply shadow matrix. mFirstDidConcat = false; - EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X + TRANSLATE_X, CASTER_Y + TRANSLATE_Y), + EXPECT_EQ(SkM44::Translate(CASTER_X + TRANSLATE_X, CASTER_Y + TRANSLATE_Y), matrix); - EXPECT_EQ(SkMatrix::MakeTrans(CASTER_X + TRANSLATE_X, CASTER_Y + TRANSLATE_Y), + EXPECT_EQ(SkMatrix::Translate(CASTER_X + TRANSLATE_X, CASTER_Y + TRANSLATE_Y), getTotalMatrix()); } else { // Second invocation is preparing the matrix for an elevated RenderNodeDrawable. - EXPECT_EQ(SkMatrix::MakeTrans(TRANSLATE_X, TRANSLATE_Y), matrix); - EXPECT_EQ(SkMatrix::MakeTrans(TRANSLATE_X, TRANSLATE_Y), getTotalMatrix()); + EXPECT_EQ(SkM44::Translate(TRANSLATE_X, TRANSLATE_Y), matrix); + EXPECT_EQ(SkMatrix::Translate(TRANSLATE_X, TRANSLATE_Y), getTotalMatrix()); } } diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp index 74a565439f85..2d34b0980546 100644 --- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp +++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp @@ -263,10 +263,10 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren_vdOffscr } // Another way to be offscreen: a matrix from the draw call. - for (const SkMatrix translate : { SkMatrix::MakeTrans(width, 0), - SkMatrix::MakeTrans(0, height), - SkMatrix::MakeTrans(-width, 0), - SkMatrix::MakeTrans(0, -height)}) { + for (const SkMatrix translate : { SkMatrix::Translate(width, 0), + SkMatrix::Translate(0, height), + SkMatrix::Translate(-width, 0), + SkMatrix::Translate(0, -height)}) { SkiaDisplayList skiaDL; VectorDrawableRoot dirtyVD(new VectorDrawable::Group()); dirtyVD.mutateProperties()->setBounds(bounds); @@ -291,7 +291,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren_vdOffscr SkiaDisplayList skiaDL; VectorDrawableRoot dirtyVD(new VectorDrawable::Group()); dirtyVD.mutateProperties()->setBounds(bounds); - SkMatrix translate = SkMatrix::MakeTrans(50, 50); + SkMatrix translate = SkMatrix::Translate(50, 50); skiaDL.appendVD(&dirtyVD, translate); ASSERT_TRUE(dirtyVD.isDirty()); diff --git a/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp b/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp index eec25c6bd40d..15ecf5831f3a 100644 --- a/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp +++ b/libs/hwui/tests/unit/SkiaRenderPropertiesTests.cpp @@ -111,11 +111,11 @@ TEST(RenderNodeDrawable, renderPropTransform) { [](RenderProperties& properties) { properties.setLeftTopRightBottom(10, 10, 110, 110); - SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); + SkMatrix staticMatrix = SkMatrix::Scale(1.2f, 1.2f); properties.setStaticMatrix(&staticMatrix); // ignored, since static overrides animation - SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); + SkMatrix animationMatrix = SkMatrix::Translate(15, 15); properties.setAnimationMatrix(&animationMatrix); properties.setTranslationX(10); diff --git a/location/java/com/android/internal/location/timezone/LocationTimeZoneEvent.java b/location/java/com/android/internal/location/timezone/LocationTimeZoneEvent.java index 7eb843e93e68..31c27d1bb977 100644 --- a/location/java/com/android/internal/location/timezone/LocationTimeZoneEvent.java +++ b/location/java/com/android/internal/location/timezone/LocationTimeZoneEvent.java @@ -24,6 +24,7 @@ import android.os.Parcelable; import com.android.internal.util.Preconditions; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -70,30 +71,30 @@ public final class LocationTimeZoneEvent implements Parcelable { @NonNull private final List<String> mTimeZoneIds; - private final long mElapsedRealtimeNanos; + private final long mElapsedRealtimeMillis; private LocationTimeZoneEvent(@EventType int eventType, @NonNull List<String> timeZoneIds, - long elapsedRealtimeNanos) { + long elapsedRealtimeMillis) { mEventType = checkValidEventType(eventType); mTimeZoneIds = immutableList(timeZoneIds); boolean emptyTimeZoneIdListExpected = eventType != EVENT_TYPE_SUCCESS; Preconditions.checkState(!emptyTimeZoneIdListExpected || timeZoneIds.isEmpty()); - mElapsedRealtimeNanos = elapsedRealtimeNanos; + mElapsedRealtimeMillis = elapsedRealtimeMillis; } /** * Returns the time of this fix, in elapsed real-time since system boot. * * <p>This value can be reliably compared to {@link - * android.os.SystemClock#elapsedRealtimeNanos}, to calculate the age of a fix and to compare + * android.os.SystemClock#elapsedRealtime()}, to calculate the age of a fix and to compare * {@link LocationTimeZoneEvent} instances. * - * @return elapsed real-time of fix, in nanoseconds since system boot. + * @return elapsed real-time of fix, in milliseconds */ - public long getElapsedRealtimeNanos() { - return mElapsedRealtimeNanos; + public long getElapsedRealtimeMillis() { + return mElapsedRealtimeMillis; } /** @@ -118,7 +119,8 @@ public final class LocationTimeZoneEvent implements Parcelable { return "LocationTimeZoneEvent{" + "mEventType=" + mEventType + ", mTimeZoneIds=" + mTimeZoneIds - + ", mElapsedRealtimeNanos=" + mElapsedRealtimeNanos + + ", mElapsedRealtimeMillis=" + mElapsedRealtimeMillis + + "(" + Duration.ofMillis(mElapsedRealtimeMillis) + ")" + '}'; } @@ -130,8 +132,8 @@ public final class LocationTimeZoneEvent implements Parcelable { @SuppressWarnings("unchecked") ArrayList<String> timeZoneIds = (ArrayList<String>) in.readArrayList(null /* classLoader */); - long elapsedRealtimeNanos = in.readLong(); - return new LocationTimeZoneEvent(eventType, timeZoneIds, elapsedRealtimeNanos); + long elapsedRealtimeMillis = in.readLong(); + return new LocationTimeZoneEvent(eventType, timeZoneIds, elapsedRealtimeMillis); } @Override @@ -149,7 +151,7 @@ public final class LocationTimeZoneEvent implements Parcelable { public void writeToParcel(Parcel parcel, int flags) { parcel.writeInt(mEventType); parcel.writeList(mTimeZoneIds); - parcel.writeLong(mElapsedRealtimeNanos); + parcel.writeLong(mElapsedRealtimeMillis); } @Override @@ -162,13 +164,13 @@ public final class LocationTimeZoneEvent implements Parcelable { } LocationTimeZoneEvent that = (LocationTimeZoneEvent) o; return mEventType == that.mEventType - && mElapsedRealtimeNanos == that.mElapsedRealtimeNanos + && mElapsedRealtimeMillis == that.mElapsedRealtimeMillis && mTimeZoneIds.equals(that.mTimeZoneIds); } @Override public int hashCode() { - return Objects.hash(mEventType, mTimeZoneIds, mElapsedRealtimeNanos); + return Objects.hash(mEventType, mTimeZoneIds, mElapsedRealtimeMillis); } /** @hide */ @@ -176,7 +178,7 @@ public final class LocationTimeZoneEvent implements Parcelable { private @EventType int mEventType = EVENT_TYPE_UNKNOWN; private @NonNull List<String> mTimeZoneIds = Collections.emptyList(); - private long mElapsedRealtimeNanos; + private long mElapsedRealtimeMillis; public Builder() { } @@ -187,7 +189,7 @@ public final class LocationTimeZoneEvent implements Parcelable { public Builder(@NonNull LocationTimeZoneEvent ltz) { mEventType = ltz.mEventType; mTimeZoneIds = ltz.mTimeZoneIds; - mElapsedRealtimeNanos = ltz.mElapsedRealtimeNanos; + mElapsedRealtimeMillis = ltz.mElapsedRealtimeMillis; } /** @@ -210,8 +212,8 @@ public final class LocationTimeZoneEvent implements Parcelable { /** * Sets the time of this event, in elapsed real-time since system boot. */ - public Builder setElapsedRealtimeNanos(long time) { - mElapsedRealtimeNanos = time; + public Builder setElapsedRealtimeMillis(long time) { + mElapsedRealtimeMillis = time; return this; } @@ -219,7 +221,7 @@ public final class LocationTimeZoneEvent implements Parcelable { * Builds a {@link LocationTimeZoneEvent} instance. */ public LocationTimeZoneEvent build() { - return new LocationTimeZoneEvent(mEventType, mTimeZoneIds, mElapsedRealtimeNanos); + return new LocationTimeZoneEvent(mEventType, mTimeZoneIds, mElapsedRealtimeMillis); } } diff --git a/location/lib/java/com/android/location/timezone/provider/LocationTimeZoneEventUnbundled.java b/location/lib/java/com/android/location/timezone/provider/LocationTimeZoneEventUnbundled.java index d044c0b52939..55f554554474 100644 --- a/location/lib/java/com/android/location/timezone/provider/LocationTimeZoneEventUnbundled.java +++ b/location/lib/java/com/android/location/timezone/provider/LocationTimeZoneEventUnbundled.java @@ -147,7 +147,7 @@ public final class LocationTimeZoneEventUnbundled { LocationTimeZoneEvent event = new LocationTimeZoneEvent.Builder() .setEventType(internalEventType) .setTimeZoneIds(mTimeZoneIds) - .setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()) + .setElapsedRealtimeMillis(SystemClock.elapsedRealtime()) .build(); return new LocationTimeZoneEventUnbundled(event); } diff --git a/native/webview/plat_support/draw_fn.h b/native/webview/plat_support/draw_fn.h index 42cad43af8fc..44fe56fcaf4b 100644 --- a/native/webview/plat_support/draw_fn.h +++ b/native/webview/plat_support/draw_fn.h @@ -10,6 +10,7 @@ #ifndef ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_FN_H_ #define ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_FN_H_ +#include <android/surface_control.h> #include <vulkan/vulkan.h> #ifdef __cplusplus @@ -21,7 +22,31 @@ extern "C" { // // 1 is Android Q. This matches kAwDrawGLInfoVersion version 3. // 2 Adds transfer_function_* and color_space_toXYZD50 to AwDrawFn_DrawGLParams. -static const int kAwDrawFnVersion = 2; +// 3 Adds SurfaceControl related functions. +static const int kAwDrawFnVersion = 3; + +// Returns parent ASurfaceControl for WebView overlays. It will be have same +// geometry as the surface we draw into and positioned below it (underlay). +// This does not pass ownership to webview, but guaranteed to be alive until +// transaction from next removeOverlays call or functor destruction will be +// finished. +typedef ASurfaceControl* AwDrawFn_GetSurfaceControl(); + +// Merges WebView transaction to be applied synchronously with current draw. +// This doesn't pass ownership of the transaction, changes will be copied and +// webview can free transaction right after the call. +typedef void AwDrawFn_MergeTransaction(ASurfaceTransaction* transaction); + +enum AwDrawFnOverlaysMode { + // Indicated that webview should not promote anything to overlays this draw + // and remove all visible overlays. + // Added in version 3. + AW_DRAW_FN_OVERLAYS_MODE_DISABLED = 0, + + // Indicates that webview can use overlays. + // Added in version 3. + AW_DRAW_FN_OVERLAYS_MODE_ENABLED = 1, +}; struct AwDrawFn_OnSyncParams { int version; @@ -60,6 +85,19 @@ struct AwDrawFn_DrawGLParams { float transfer_function_e; float transfer_function_f; float color_space_toXYZD50[9]; + + // Input: Indicates how webview should use overlays for this draw. + // Added in version 3. + AwDrawFnOverlaysMode overlays_mode; + + // Input: WebView can call it to obtain parent surface control for overlays. + // Added in version 3. + AwDrawFn_GetSurfaceControl* get_surface_control; + + // Input: WebView call this to apply ASurfaceTransaction synchronously with + // the draw. + // Added in version 3. + AwDrawFn_MergeTransaction* merge_transaction; }; struct AwDrawFn_InitVkParams { @@ -122,12 +160,33 @@ struct AwDrawFn_DrawVkParams { int clip_top; int clip_right; int clip_bottom; + + // Input: Indicates how webview should use overlays for this draw. + // Added in version 3. + AwDrawFnOverlaysMode overlays_mode; + + // Input: WebView can call it to obtain parent surface control for overlays. + // Added in version 3. + AwDrawFn_GetSurfaceControl* get_surface_control; + + // Input: WebView call this to apply ASurfaceTransaction synchronously with + // the draw. + // Added in version 3. + AwDrawFn_MergeTransaction* merge_transaction; }; struct AwDrawFn_PostDrawVkParams { int version; }; +struct AwDrawFn_RemoveOverlaysParams { + int version; + // Input: WebView call this to apply ASurfaceTransaction synchronously with + // the draw. + // Added in version 3. + AwDrawFn_MergeTransaction* merge_transaction; +}; + // Called on render thread while UI thread is blocked. Called for both GL and // VK. typedef void AwDrawFn_OnSync(int functor, @@ -166,8 +225,15 @@ typedef void AwDrawFn_PostDrawVk(int functor, void* data, AwDrawFn_PostDrawVkParams* params); +// Can be called to make webview hide all overlays and stop updating them until +// next draw. WebView must obtain new ASurfaceControl after this call to use as +// parent for the overlays on next draw. +typedef void AwDrawFn_RemoveOverlays(int functor, + void* data, + AwDrawFn_RemoveOverlaysParams* params); + struct AwDrawFnFunctorCallbacks { - // No version here since this is passed from chromium to android. + // version is passed in CreateFunctor call. AwDrawFn_OnSync* on_sync; AwDrawFn_OnContextDestroyed* on_context_destroyed; AwDrawFn_OnDestroyed* on_destroyed; @@ -175,6 +241,8 @@ struct AwDrawFnFunctorCallbacks { AwDrawFn_InitVk* init_vk; AwDrawFn_DrawVk* draw_vk; AwDrawFn_PostDrawVk* post_draw_vk; + // Added in version 3. + AwDrawFn_RemoveOverlays* remove_overlays; }; enum AwDrawFnRenderMode { @@ -185,10 +253,16 @@ enum AwDrawFnRenderMode { // Get the render mode. Result is static for the process. typedef AwDrawFnRenderMode AwDrawFn_QueryRenderMode(void); -// Create a functor. |functor_callbacks| should be valid until OnDestroyed. +// This available up to version 3, use the one below. typedef int AwDrawFn_CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks); +// Create a functor. |functor_callbacks| should be valid until OnDestroyed. +typedef int AwDrawFn_CreateFunctor_v3( + void* data, + int version, + AwDrawFnFunctorCallbacks* functor_callbacks); + // May be called on any thread to signal that the functor should be destroyed. // The functor will receive an onDestroyed when the last usage of it is // released, and it should be considered alive & active until that point. @@ -197,8 +271,11 @@ typedef void AwDrawFn_ReleaseFunctor(int functor); struct AwDrawFnFunctionTable { int version; AwDrawFn_QueryRenderMode* query_render_mode; + // Available up to version 3. AwDrawFn_CreateFunctor* create_functor; AwDrawFn_ReleaseFunctor* release_functor; + // Added in version 3. + AwDrawFn_CreateFunctor_v3* create_functor_v3; }; #ifdef __cplusplus diff --git a/native/webview/plat_support/draw_functor.cpp b/native/webview/plat_support/draw_functor.cpp index 7cce61b87d12..ea57ea070369 100644 --- a/native/webview/plat_support/draw_functor.cpp +++ b/native/webview/plat_support/draw_functor.cpp @@ -32,6 +32,15 @@ struct SupportData { AwDrawFnFunctorCallbacks callbacks; }; +AwDrawFnOverlaysMode GetOverlaysMode(uirenderer::OverlaysMode overlays_mode) { + switch (overlays_mode) { + case uirenderer::OverlaysMode::Disabled: + return AW_DRAW_FN_OVERLAYS_MODE_DISABLED; + case uirenderer::OverlaysMode::Enabled: + return AW_DRAW_FN_OVERLAYS_MODE_ENABLED; + } +} + void onSync(int functor, void* data, const uirenderer::WebViewSyncData& syncData) { AwDrawFn_OnSyncParams params = { @@ -53,8 +62,20 @@ void onDestroyed(int functor, void* data) { delete support; } +void removeOverlays(int functor, void* data, + AwDrawFn_MergeTransaction merge_transaction) { + AwDrawFn_RemoveOverlaysParams params = { + .version = kAwDrawFnVersion, + .merge_transaction = merge_transaction + }; + SupportData* support = static_cast<SupportData*>(data); + if (support->callbacks.remove_overlays) + support->callbacks.remove_overlays(functor, support->data, ¶ms); +} + void draw_gl(int functor, void* data, - const uirenderer::DrawGlInfo& draw_gl_params) { + const uirenderer::DrawGlInfo& draw_gl_params, + const uirenderer::WebViewOverlayData& overlay_params) { float gabcdef[7]; draw_gl_params.color_space_ptr->transferFn(gabcdef); AwDrawFn_DrawGLParams params = { @@ -73,6 +94,9 @@ void draw_gl(int functor, void* data, .transfer_function_d = gabcdef[4], .transfer_function_e = gabcdef[5], .transfer_function_f = gabcdef[6], + .overlays_mode = GetOverlaysMode(overlay_params.overlaysMode), + .get_surface_control = overlay_params.getSurfaceControl, + .merge_transaction = overlay_params.mergeTransaction }; COMPILE_ASSERT(NELEM(params.transform) == NELEM(draw_gl_params.transform), mismatched_transform_matrix_sizes); @@ -118,7 +142,9 @@ void initializeVk(int functor, void* data, support->callbacks.init_vk(functor, support->data, ¶ms); } -void drawVk(int functor, void* data, const uirenderer::VkFunctorDrawParams& draw_vk_params) { +void drawVk(int functor, void* data, + const uirenderer::VkFunctorDrawParams& draw_vk_params, + const uirenderer::WebViewOverlayData& overlay_params) { SupportData* support = static_cast<SupportData*>(data); float gabcdef[7]; draw_vk_params.color_space_ptr->transferFn(gabcdef); @@ -142,6 +168,9 @@ void drawVk(int functor, void* data, const uirenderer::VkFunctorDrawParams& draw .clip_top = draw_vk_params.clip_top, .clip_right = draw_vk_params.clip_right, .clip_bottom = draw_vk_params.clip_bottom, + .overlays_mode = GetOverlaysMode(overlay_params.overlaysMode), + .get_surface_control = overlay_params.getSurfaceControl, + .merge_transaction = overlay_params.mergeTransaction }; COMPILE_ASSERT(sizeof(params.color_space_toXYZD50) == sizeof(skcms_Matrix3x3), gamut_transform_size_mismatch); @@ -161,12 +190,14 @@ void postDrawVk(int functor, void* data) { support->callbacks.post_draw_vk(functor, support->data, ¶ms); } -int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { +int CreateFunctor_v3(void* data, int version, + AwDrawFnFunctorCallbacks* functor_callbacks) { static bool callbacks_initialized = false; static uirenderer::WebViewFunctorCallbacks webview_functor_callbacks = { .onSync = &onSync, .onContextDestroyed = &onContextDestroyed, .onDestroyed = &onDestroyed, + .removeOverlays = &removeOverlays, }; if (!callbacks_initialized) { switch (uirenderer::WebViewFunctor_queryPlatformRenderMode()) { @@ -183,8 +214,23 @@ int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { } SupportData* support = new SupportData{ .data = data, - .callbacks = *functor_callbacks, }; + + // These callbacks are available on all versions. + support->callbacks = { + .on_sync = functor_callbacks->on_sync, + .on_context_destroyed = functor_callbacks->on_context_destroyed, + .on_destroyed = functor_callbacks->on_destroyed, + .draw_gl = functor_callbacks->draw_gl, + .init_vk = functor_callbacks->init_vk, + .draw_vk = functor_callbacks->draw_vk, + .post_draw_vk = functor_callbacks->post_draw_vk, + }; + + if (version >= 3) { + support->callbacks.remove_overlays = functor_callbacks->remove_overlays; + } + int functor = uirenderer::WebViewFunctor_create( support, webview_functor_callbacks, uirenderer::WebViewFunctor_queryPlatformRenderMode()); @@ -192,6 +238,12 @@ int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { return functor; } +int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) { + const int kVersionForDeprecatedCreateFunctor = 2; + return CreateFunctor_v3(data, kVersionForDeprecatedCreateFunctor, + functor_callbacks); +} + void ReleaseFunctor(int functor) { uirenderer::WebViewFunctor_release(functor); } @@ -211,6 +263,7 @@ jlong GetDrawFnFunctionTable() { .query_render_mode = &QueryRenderMode, .create_functor = &CreateFunctor, .release_functor = &ReleaseFunctor, + .create_functor_v3 = &CreateFunctor_v3, }; return reinterpret_cast<intptr_t>(&function_table); } diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 2b30e0a61863..41af185da0b7 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> oor tot battery gelaai is"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot battery gelaai is"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery word tydelik beperk"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 0bebfabf2eb9..8e4e402c2e16 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ኃይል እስከሚሞላ ድረስ ይቀራል"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ኃይል እስከሚሞላ ድረስ"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ባትሪ ለጊዜው ተገድቧል"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 6eaf3a98da11..691ec046da02 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - تأثير محدود على البطارية مؤقتًا"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index e207e1ce4c12..61214e09ba26 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"চাৰ্জ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> চাৰ্জ হ\'বলৈ"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেটাৰী সাময়িকভাৱে সীমিত কৰা হৈছে"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index ff1209c754d1..db61527a54d8 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Enerjinin dolmasına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjinin dolmasına <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batareya müvəqqəti məhdudlaşdırılıb"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index eb099c1926a7..70fb3636b492 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napuniće se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napuniće se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterija je trenutno ograničena"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index e6e49ab2063c..8a0db8261a71 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Засталося <xliff:g id="TIME">%1$s</xliff:g> да поўнай зарадкі"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарад акумулятара часова абмежаваны"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 251c4dd545c4..27dcf105fd2e 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Батерията е временно ограничена"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 6a99a84358d4..29862e6efd31 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -211,9 +211,9 @@ <string name="adb_wireless_error" msgid="721958772149779856">"সমস্যা"</string> <string name="adb_wireless_settings" msgid="2295017847215680229">"ওয়্যারলেস ডিবাগিং"</string> <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"কোন কোন ডিভাইস উপলভ্য আছে তা দেখে নিয়ে ব্যবহার করার জন্য, ওয়্যারলেস ডিবাগিং চালু করুন"</string> - <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR কোড ব্যবহার করে ডিভাইস যোগ করুন"</string> + <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR কোড ব্যবহার করে ডিভাইসের সাথে পেয়ার করুন"</string> <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"QR কোড স্ক্যানার ব্যবহার করে নতুন ডিভাইস যোগ করুন"</string> - <string name="adb_pair_method_code_title" msgid="1122590300445142904">"যোগ করার কোড ব্যবহার করে ডিভাইস যোগ করুন"</string> + <string name="adb_pair_method_code_title" msgid="1122590300445142904">"পেয়ারিং কোড ব্যবহার করে ডিভাইসের সাথে পেয়ার করুন"</string> <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ছয় সংখ্যার কোড ব্যবহার করে নতুন ডিভাইস যোগ করুন"</string> <string name="adb_paired_devices_title" msgid="5268997341526217362">"যোগ করা ডিভাইস"</string> <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"এখন কানেক্ট রয়েছে"</string> @@ -222,16 +222,16 @@ <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ডিভাইসে আঙ্গুলের ছাপ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string> <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"কানেক্ট করা যায়নি"</string> <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>টি সঠিক নেটওয়ার্কে কানেক্ট আছে কিনা দেখে নিন"</string> - <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ডিভাইসের সাথে যোগ করুন"</string> - <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"ওয়াই-ফাই যোগ করার কোড"</string> - <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"যোগ করা যায়নি"</string> + <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ডিভাইসের সাথে পেয়ার করুন"</string> + <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"ওয়াই-ফাইয়ের সাথে পেয়ার করার কোড"</string> + <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"পেয়ার করা যায়নি"</string> <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ডিভাইসটি একই নেটওয়ার্কে কানেক্ট আছে কিনা দেখে নিন।"</string> - <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR কোড স্ক্যান করে ওয়াই-ফাই ব্যবহার করে ডিভাইস যোগ করুন"</string> + <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR কোড স্ক্যান করে ওয়াই-ফাই ব্যবহার করে ডিভাইসের সাথে পেয়ার করুন"</string> <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ডিভাইস যোগ করা হচ্ছে…"</string> <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ডিভাইস যোগ করা যায়নি। এটি দুটি কারণে হয়ে থাকে - QR কোডটি সঠিক নয় বা ডিভাইসটি একই নেটওয়ার্কে কানেক্ট করা নেই।"</string> <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP অ্যাড্রেস ও পোর্ট"</string> <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR কোড স্ক্যান করুন"</string> - <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"QR কোড স্ক্যান করে ওয়াই-ফাইয়ের সাহায্যে ডিভাইস যোগ করুন"</string> + <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"QR কোড স্ক্যান করে ওয়াই-ফাই ব্যবহার করে ডিভাইসের সাথে পেয়ার করুন"</string> <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"একটি ওয়াই-ফাই নেটওয়ার্কের সাথে কানেক্ট করুন"</string> <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string> <string name="bugreport_in_power" msgid="8664089072534638709">"ত্রুটি প্রতিবেদনের শর্টকাট"</string> @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি আছে"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ সম্পূর্ণ চার্জ হয়ে যাবে"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ব্যাটারি কিছুক্ষণের জন্য সীমিত করা হয়েছে"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index aeb7f2ecc567..4704ec8db79a 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterija je privremeno ograničena"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index df4c99e20505..5d04963d9b4a 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -66,7 +66,7 @@ <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconnectat"</string> <string name="bluetooth_disconnecting" msgid="7638892134401574338">"S\'està desconnectant..."</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"S\'està connectant…"</string> - <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connectat"</string> + <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> Connectat"</string> <string name="bluetooth_pairing" msgid="4269046942588193600">"S\'està vinculant..."</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connectat (sense accés al telèfon)"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connectat (sense contingut multimèdia)"</string> @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporalment"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index e563ca5a03f8..a99a4dabbc60 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do nabití zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do nabití"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterie dočasně omezena"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 8a3d054c3ae8..c90155eb2b68 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batteriet er midlertidigt begrænset"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index 624b299a96c3..b5b9fc480607 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Inaktiv. Zum Wechseln tippen."</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Zum Wechseln tippen."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Standby-Status der App:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"Einstellungen für Medientranscodierung"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"Transcodierung deaktivieren"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"Transcodierung für Apps aktivieren"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive Dienste"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Momentan ausgeführte Dienste anzeigen und steuern"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-Implementierung"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Noch <xliff:g id="TIME">%1$s</xliff:g> bis zur Aufladung"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis zur Aufladung"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akku vorübergehend eingeschränkt"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 7ea90506ac06..203ec40c5a42 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για ολοκλήρωση της φόρτισης"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για την ολοκλήρωση της φόρτισης"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η μπαταρία περιορίστηκε προσωρινά."</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 7affb5c89dfc..08ff55099c9c 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -196,7 +196,7 @@ <string name="choose_profile" msgid="343803890897657450">"Elegir perfil"</string> <string name="category_personal" msgid="6236798763159385225">"Personal"</string> <string name="category_work" msgid="4014193632325996115">"Trabajo"</string> - <string name="development_settings_title" msgid="140296922921597393">"Opciones para programadores"</string> + <string name="development_settings_title" msgid="140296922921597393">"Opciones para desarrolladores"</string> <string name="development_settings_enable" msgid="4285094651288242183">"Activar opciones para programador"</string> <string name="development_settings_summary" msgid="8718917813868735095">"Establecer opciones para desarrollar aplicaciones"</string> <string name="development_settings_not_available" msgid="355070198089140951">"Las opciones de programador no están disponibles para este usuario."</string> @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batería limitada temporalmente"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápido"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index ccdc1c443fbd..6f6a1a1c9b17 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> hasta cargarse completamente"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> hasta cargarse completamente)"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: batería limitada temporalmente"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 852d6df7d31e..9d6326e45706 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Täislaadimiseni on jäänud <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – akutase on ajutiselt piiratud"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 6b6b9b63df65..01afa1706e3e 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria mugatuta egongo da aldi batez"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index af1e55be67c5..dd7ab9672e96 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> مانده تا شارژ کامل"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - باتری موقتاً محدود شده است"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 8e819efe3557..b86b02d8c25f 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä täyteen lataukseen"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akun käyttöä rajoitettu tilapäisesti"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 4754d15b5a52..0bca1dba1aa4 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Pile limitée temporairement"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index a3863f596067..ebde43ba52a2 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à ce que la batterie soit chargée"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batterie limitée temporairement"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index 81e79e4a27a9..b040817b2801 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> (batería limitada temporalmente)"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 9bf09704a4f5..c1bd7cac30a6 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"નિષ્ક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"સક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ઍપ સ્ટૅન્ડબાયની સ્થિતિ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"મીડિયાનું ફૉર્મેટ બદલવાની પ્રક્રિયાના સેટિંગ"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"ફૉર્મેટ બદલવાની પ્રક્રિયા બંધ કરો"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"ઍપ માટે ફૉર્મેટ બદલવાની પ્રક્રિયા ચાલુ કરો"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ચાલુ સેવાઓ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"હાલમાં ચાલતી સેવાઓ જુઓ અને નિયંત્રિત કરો"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView અમલીકરણ"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - બૅટરીનો વપરાશ હંગામી રૂપે મર્યાદિત છે"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 151b861cbd3b..d9153a1ab542 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"चार्ज पूरा होने में <xliff:g id="TIME">%1$s</xliff:g> बचा है"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में पूरा चार्ज हो जाएगा"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - कुछ समय के लिए, बैटरी का सीमित इस्तेमाल होगा"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index d37879f6e153..b51e096ca6b7 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterija je privremeno ograničena"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 4ac5308474c5..33770fc1bdd8 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> van hátra a feltöltésből"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akkumulátor ideiglenesen korlátozva"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index b0734fdee27e..06d70f854f27 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լիցքավորումը"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լիցքավորումը"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Մարտկոցը ժամանակավորապես սահմանափակված է"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 9db21c796bbf..4123d9e3b755 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Sisa <xliff:g id="TIME">%1$s</xliff:g> hingga terisi penuh"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Daya baterai terbatas untuk sementara"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index d9ee03adefa4..3b9bef872177 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> að fullri hleðslu"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> að fullri hleðslu"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Rafhlaða takmörkuð tímabundið"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 57378e78af65..1ab6b24456f3 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -66,7 +66,7 @@ <string name="bluetooth_disconnected" msgid="7739366554710388701">"Disconnesso"</string> <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Disconnessione…"</string> <string name="bluetooth_connecting" msgid="5871702668260192755">"Connessione…"</string> - <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso"</string> + <string name="bluetooth_connected" msgid="8065345572198502293">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> Connesso"</string> <string name="bluetooth_pairing" msgid="4269046942588193600">"Accoppiamento…"</string> <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (telefono escluso)"</string> <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g> connesso (contenuti multimediali esclusi)"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index fd53f14bd48f..15868d5fc997 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"אפליקציה לא פעילה. הקש כדי להחליף מצב."</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"אפליקציה פעילה. הקש כדי להחליף מצב."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"אפליקציה במצב המתנה:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"הגדרות של המרת קידוד למדיה"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"השבתה של המרת קידוד"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"הפעלה של המרת קידוד לאפליקציות"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"שירותים פועלים"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"הצגת השירותים הפועלים כעת ושליטה בהם"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"יישום WebView"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"נשארו <xliff:g id="TIME">%1$s</xliff:g> עד הטעינה"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד הטעינה"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - הסוללה מוגבלת באופן זמני"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index c0aa74bafc56..89ee98eeeb42 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"充電完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電完了まで <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池の使用が一時的に制限されています"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 09f3ff5c957a..2bc1c4d20728 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарея жұмысы уақытша шектелген"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядталуда"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 42e6a53a0078..7306cf8c5d3f 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានដាក់កម្រិតថ្មជាបណ្ដោះអាសន្ន"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"មិនស្គាល់"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងបញ្ចូលថ្ម"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 658b987dd833..0c1502ca620d 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಇದೆ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬೇಕು"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಬ್ಯಾಟರಿ ತಾತ್ಕಾಲಿಕವಾಗಿ ಸೀಮಿತವಾಗಿದೆ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 2b0843dcef39..13223440d098 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 일시적으로 배터리 사용 제한"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 499fd88f5a4f..9697aa70e44f 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталып бүтөт"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталып бүтөт"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареяны колдонуу убактлуу чектелген"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index a5be6017ca62..720122262dcf 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -399,9 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ບໍ່ໄດ້ນຳໃຊ້. ແຕະບໍ່ສັບປ່ຽນ."</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"ນຳໃຊ້ຢູ່. ແຕະເພື່ອສັບປ່ຽນ."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ສະຖານະສະແຕນບາຍແອັບ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <string name="transcode_settings_title" msgid="2581975870429850549">"ການຕັ້ງຄ່າການປ່ຽນຮູບແບບລະຫັດມີເດຍ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ປິດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດ"</string> - <string name="transcode_skip_apps" msgid="8249721984597390142">"ເປີດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດສຳລັບແອັບ"</string> + <string name="transcode_settings_title" msgid="2581975870429850549">"ການຕັ້ງຄ່າການປ່ຽນຮູບແບບລະຫັດມີເດຍ"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"ປິດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດ"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"ເປີດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດສຳລັບແອັບ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ບໍລິການທີ່ເຮັດວຽກຢູ່"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ເບິ່ງ ແລະຈັດການບໍລິການທີ່ກຳລັງເຮັດວຽກຢູ່ໃນປັດຈຸບັນ"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string> @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຈຳກັດແບັດເຕີຣີຊົ່ວຄາວ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 181fb10dd845..e62eeb2dbd97 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – iki visiškos įkrovos liko <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – akumuliatorius laikinai apribotas"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 717e2b0c89d8..2f305612a5fc 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Vēl <xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>, akumulatora uzlāde pagaidām ierobežota"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 2ccb150b8ca3..1936fe2d32a4 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Уште <xliff:g id="TIME">%1$s</xliff:g> до целосно полнење"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до целосно полнење"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батеријата е привремено ограничена"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 768ad5e70698..de4a49a2ed06 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"നിഷ്ക്രിയം. മാറ്റുന്നതിനു ടാപ്പുചെയ്യുക."</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ആപ്പ് സ്റ്റാൻഡ്ബൈ നില:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"മീഡിയ ട്രാൻസ്കോഡ് ചെയ്യൽ ക്രമീകരണം"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"ട്രാൻസ്കോഡ് ചെയ്യൽ പ്രവർത്തനരഹിതമാക്കുക"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"ആപ്പുകൾക്കായി ട്രാൻസ്കോഡ് ചെയ്യുന്നത് പ്രവർത്തനക്ഷമമാക്കുക"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"നിലവിൽ പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ കാണുക, നിയന്ത്രിക്കുക"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView നടപ്പാക്കൽ"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി താൽക്കാലം പരിമിതപ്പെടുത്തി"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 61ebca5992b8..dee8add685f9 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Цэнэглэх хүртэл үлдсэн <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - цэнэглэх хүртэл <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейг түр хугацаанд хязгаарласан"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index ef319c3a4fc1..60ad68e42c09 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"निष्क्रिय. टॉगल करण्यासाठी टॅप करा."</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"अॅप स्टँडबाय स्थिती: <xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रान्सकोडिंगची सेटिंग्ज"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रान्सकोडिंग बंद करा"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"ॲप्ससाठी ट्रान्सकोडिंग सुरू करा"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"सुरू सेवा"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"वेबदृश्य अंमलबजावणी"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - बॅटरी तात्पुरती मर्यादित आहे"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 83c038453265..e4d591207937 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Bateri terhad untuk sementara"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index f398487856bf..09a8bf87700b 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> ကျန်သည်"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ဘက်ထရီ ယာယီကန့်သတ်ထားသည်"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 0ef5809e2a6d..d1af28940f1b 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> til batteriet er fulladet"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til batteriet er fulladet"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batteriet er midlertidig begrenset"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index b956e2104c82..0c6114b9e220 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"निष्क्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"एपको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"मिडिया ट्रान्सकोडिङ सेटिङ"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रान्सकोडिङ अफ गर्नुहोस्"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"एपहरूमा ट्रान्सकोडिङ अन गर्नुहोस्"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView कार्यान्वयन"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"पूर्ण चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string> <string name="power_charging_duration" msgid="5005740040558984057">"पूर्ण चार्ज हुन <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> लाग्छ"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - केही समयका लागि ब्याट्री प्रयोग सीमित गरिएको छ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 3223857a0949..a409756e5b5f 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot opgeladen"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot opgeladen"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batterij tijdelijk beperkt"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 11bb550caa49..0a0eeff6de60 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ନିଷ୍କ୍ରିୟ। ଟୋଗଲ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"ସକ୍ରିୟ। ବଦଳାଇବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ଆପ୍ ଷ୍ଟାଣ୍ଡବାଏ ଅବସ୍ଥା:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"ମିଡିଆ ଟ୍ରାନ୍ସକୋଡିଂ ସେଟିଂସ୍"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"ଟ୍ରାନ୍ସକୋଡିଂ ଅକ୍ଷମ କରନ୍ତୁ"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"ଆପଗୁଡ଼ିକ ପାଇଁ ଟ୍ରାନ୍ସକୋଡିଂ ସକ୍ଷମ କରନ୍ତୁ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ଏବେ ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ ଓ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"ୱେବ୍ଭ୍ୟୁ ପ୍ରୟୋଗ"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ଚାର୍ଜ ହେବା ପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ବ୍ୟାଟେରୀ ଅସ୍ଥାୟୀ ଭାବେ ସୀମିତ ଅଛି"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 8d66f3ca4adc..c9c37d922537 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"ਅਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"ਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ਐਪ ਸਟੈਂਡਬਾਈ ਸਥਿਤੀ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"ਮੀਡੀਆ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਸੈਟਿੰਗਾਂ"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਬੰਦ ਕਰੋ"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"ਐਪਾਂ ਲਈ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ਅਮਲ"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਕੁਝ ਸਮੇਂ ਲਈ ਸੀਮਤ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index ed96c46848d9..e894c2cbc34c 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do naładowania <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – do naładowania <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – bateria tymczasowo ograniczona"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 46d6d0a89f5e..57a0454f3465 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> până la încărcare"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la încărcare"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterie limitată temporar"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 2a79ad3005ff..09b8de04388b 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> • Уровень заряда временно ограничен"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index 78f355865ced..d36140f66b54 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඇත"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වන තෙක් <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - බැටරිය තාවකාලිකව සීමිතයි"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්ර ආරෝපණය"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 152c7a885457..096e95e7050b 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batéria je dočasne obmedzená"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index a2f093e89ad8..345fa36d3bd6 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do polne napolnjenosti"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterija je začasno omejena"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index b4589173f234..3953a6a4f6e0 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në karikim"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të karikohet"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Bateria e kufizuar përkohësisht"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Po ngarkon me shpejtësi"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 970c70f48c68..70b287933c93 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Напуниће се за <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – напуниће се за <xliff:g id="TIME">%2$s</xliff:g>"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – батерија је тренутно ограничена"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 42d907734e30..f466e882c2fc 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> kvar till full laddning"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till full laddning"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – batteriet är tillfälligt begränsat"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index f1a41994d2c8..e1060fec2a66 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Imebakisha <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ijae chaji"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Betri imedhibitiwa kwa muda"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 2d696c5f79eb..ba98d79ff7e4 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>-பேட்டரி தற்காலிகக் கட்டுப்பாட்டிலுள்ளது"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 8e0f0b603523..0b93979dbd07 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%2$s</xliff:g> పడుతుంది"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> -బ్యాటరీ తాత్కాలికంగా పరిమితం చేయబడింది"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 81895b923a44..a31e14611bf6 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"เหลือ <xliff:g id="TIME">%1$s</xliff:g> จนกว่าจะชาร์จเต็ม"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะชาร์จ"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - การชาร์จแบตเตอรี่จำกัดชั่วคราว"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 5d1630f28675..bbb77790e68a 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago matapos mag-charge"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang matapos mag-charge"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pansamantalang limitado ang baterya"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 34c96a815616..fba7f41bbbf5 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Şarj olmaya <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - şarj olmaya <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pil geçici olarak sınırlı"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index de2456cce092..b633752d28a9 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – дані акумулятора тимчасово недоступні"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index 7842ba9bcdbf..b4d8ad2576bd 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -399,12 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"غیر فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ایپ اسٹینڈ بائی کی حالت:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <!-- no translation found for transcode_settings_title (2581975870429850549) --> - <skip /> - <!-- no translation found for transcode_enable_all (9102460144086871903) --> - <skip /> - <!-- no translation found for transcode_skip_apps (8249721984597390142) --> - <skip /> + <string name="transcode_settings_title" msgid="2581975870429850549">"میڈیا ٹرانسکوڈنگ کی ترتیبات"</string> + <string name="transcode_enable_all" msgid="9102460144086871903">"ٹرانسکوڈنگ غیر فعال کریں"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"ایپس کے لئے ٹرانسکوڈنگ فعال کریں"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"چل رہی سروسز"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"فی الحال چل رہی سروسز دیکھیں اور انہیں کنٹرول کریں"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView کا نفاذ"</string> @@ -452,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> چارج ہونے تک"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - بیٹری عارضی طور پر محدود ہے"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 9457d9001a88..5bb422ecf96a 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ichida toʻladi"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida toʻladi"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quvvat darajasi vaqtincha cheklangan"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 235987c423d5..0acf9418b718 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Còn <xliff:g id="TIME">%1$s</xliff:g> nữa là sạc đầy"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là sạc đầy"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Thời lượng pin bị hạn chế tạm thời"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 46188e9859e6..ca2ad87fb864 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"还剩 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>后充满电"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暂时限用电池"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 6f5c0253e94f..16ca19d313c1 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -399,9 +399,9 @@ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"未啟用。輕按即可切換。"</string> <string name="inactive_app_active_summary" msgid="8047630990208722344">"已啟用。輕按即可切換。"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"備用應用程式狀態:<xliff:g id="BUCKET"> %s</xliff:g>"</string> - <string name="transcode_settings_title" msgid="2581975870429850549">"媒體轉碼功能設定"</string> + <string name="transcode_settings_title" msgid="2581975870429850549">"媒體轉碼設定"</string> <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</string> - <string name="transcode_skip_apps" msgid="8249721984597390142">"替應用程式啟用轉碼功能"</string> + <string name="transcode_skip_apps" msgid="8249721984597390142">"為應用程式啟用轉碼功能"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"執行中的服務"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並控制目前正在執行中的服務"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 設置"</string> @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能充滿電"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暫時限制電池充電"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充電"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index f966df68e0c3..810119b97777 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g>後充飽電"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽電"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暫時限制電池用量"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 8ad37d330bc4..23beeb1aee82 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -449,8 +449,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> esele ize ishaje"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ize igcwale"</string> - <!-- no translation found for power_charging_limited (5902301801611726210) --> - <skip /> + <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ibhethri ikhawulelwe okwesikhashana"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java index 59d8acb82196..8fd1910041c8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java @@ -49,6 +49,7 @@ import java.util.concurrent.CopyOnWriteArrayList; */ public class BluetoothEventManager { private static final String TAG = "BluetoothEventManager"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final LocalBluetoothAdapter mLocalAdapter; private final CachedBluetoothDeviceManager mDeviceManager; @@ -366,6 +367,9 @@ public class BluetoothEventManager { * BluetoothDevice.UNBOND_REASON_* */ private void showUnbondMessage(Context context, String name, int reason) { + if (DEBUG) { + Log.d(TAG, "showUnbondMessage() name : " + name + ", reason : " + reason); + } int errorMsg; switch (reason) { @@ -382,6 +386,7 @@ public class BluetoothEventManager { case BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT: case BluetoothDevice.UNBOND_REASON_REPEATED_ATTEMPTS: case BluetoothDevice.UNBOND_REASON_REMOTE_AUTH_CANCELED: + case BluetoothDevice.UNBOND_REASON_REMOVED: errorMsg = R.string.bluetooth_pairing_error_message; break; default: diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java index ba1dc64ce1e6..6a4d650ebf31 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java @@ -35,6 +35,8 @@ import android.content.IntentFilter; import android.os.UserHandle; import android.telephony.TelephonyManager; +import com.android.settingslib.R; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -49,6 +51,8 @@ import java.util.List; @RunWith(RobolectricTestRunner.class) public class BluetoothEventManagerTest { + private static final String DEVICE_NAME = "test_device_name"; + @Mock private LocalBluetoothAdapter mLocalAdapter; @Mock @@ -71,6 +75,8 @@ public class BluetoothEventManagerTest { private BluetoothDevice mDevice2; @Mock private LocalBluetoothProfileManager mLocalProfileManager; + @Mock + private BluetoothUtils.ErrorListener mErrorListener; private Context mContext; private Intent mIntent; @@ -92,6 +98,7 @@ public class BluetoothEventManagerTest { mCachedDevice1 = new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1); mCachedDevice2 = new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2); + BluetoothUtils.setErrorListener(mErrorListener); } @Test @@ -344,4 +351,80 @@ public class BluetoothEventManagerTest { assertThat(mCachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(mCachedDevice2.isActiveDevice(BluetoothProfile.HEARING_AID)).isFalse(); } + + @Test + public void showUnbondMessage_reasonRemoved_showCorrectedErrorCode() { + mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); + mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); + mIntent.putExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.UNBOND_REASON_REMOVED); + when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1); + when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME); + + mContext.sendBroadcast(mIntent); + + verify(mErrorListener).onShowError(any(Context.class), eq(DEVICE_NAME), + eq(R.string.bluetooth_pairing_error_message)); + } + + @Test + public void showUnbondMessage_reasonAuthTimeout_showCorrectedErrorCode() { + mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); + mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); + mIntent.putExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.UNBOND_REASON_AUTH_TIMEOUT); + when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1); + when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME); + + mContext.sendBroadcast(mIntent); + + verify(mErrorListener).onShowError(any(Context.class), eq(DEVICE_NAME), + eq(R.string.bluetooth_pairing_error_message)); + } + + @Test + public void showUnbondMessage_reasonRemoteDeviceDown_showCorrectedErrorCode() { + mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); + mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); + mIntent.putExtra(BluetoothDevice.EXTRA_REASON, + BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN); + when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1); + when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME); + + mContext.sendBroadcast(mIntent); + + verify(mErrorListener).onShowError(any(Context.class), eq(DEVICE_NAME), + eq(R.string.bluetooth_pairing_device_down_error_message)); + } + + @Test + public void showUnbondMessage_reasonAuthRejected_showCorrectedErrorCode() { + mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); + mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); + mIntent.putExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.UNBOND_REASON_AUTH_REJECTED); + when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1); + when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME); + + mContext.sendBroadcast(mIntent); + + verify(mErrorListener).onShowError(any(Context.class), eq(DEVICE_NAME), + eq(R.string.bluetooth_pairing_rejected_error_message)); + } + + @Test + public void showUnbondMessage_reasonAuthFailed_showCorrectedErrorCode() { + mIntent = new Intent(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice); + mIntent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); + mIntent.putExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.UNBOND_REASON_AUTH_FAILED); + when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedDevice1); + when(mCachedDevice1.getName()).thenReturn(DEVICE_NAME); + + mContext.sendBroadcast(mIntent); + + verify(mErrorListener).onShowError(any(Context.class), eq(DEVICE_NAME), + eq(R.string.bluetooth_pairing_pin_error_message)); + } } diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index b75c2c4cea6c..c82bda6620bd 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -95,7 +95,7 @@ android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="center_horizontal" - android:textSize="170dp" + android:textSize="180dp" android:letterSpacing="0.02" android:lineSpacingMultiplier=".8" android:includeFontPadding="false" diff --git a/packages/SystemUI/res-product/values/strings.xml b/packages/SystemUI/res-product/values/strings.xml index f1c539e8eb4e..c1e81bacbec5 100644 --- a/packages/SystemUI/res-product/values/strings.xml +++ b/packages/SystemUI/res-product/values/strings.xml @@ -23,7 +23,7 @@ <!-- Indication when device is not charging due to bad placement on the dock. [CHAR LIMIT=60] --> <string name="dock_alignment_not_charging" product="default">Realign phone to charge wirelessly</string> - <!-- Message of the overlay warning the user to interact with the device or it will go to sleep. [CHAR LIMIT=NONE] --> + <!-- Message of the overlay warning the user that the TV is about to go to standby unless a TV remote button is pressed. [CHAR LIMIT=NONE] --> <string name="inattentive_sleep_warning_message" product="tv">The Android TV device will soon turn off; press a button to keep it on.</string> <!-- Message of the overlay warning the user to interact with the device or it will go to sleep. [CHAR LIMIT=NONE] --> <string name="inattentive_sleep_warning_message" product="default">The device will soon turn off; press to keep it on.</string> diff --git a/packages/SystemUI/res/layout/global_actions_grid_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_v2.xml index 7d45de3fa50d..30ffc32ce1f8 100644 --- a/packages/SystemUI/res/layout/global_actions_grid_v2.xml +++ b/packages/SystemUI/res/layout/global_actions_grid_v2.xml @@ -1,67 +1,15 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/global_actions_container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > - <com.android.systemui.globalactions.GlobalActionsFlatLayout - android:id="@id/global_actions_view" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:theme="@style/qs_theme" - android:clipChildren="false" - android:clipToPadding="false" - android:layout_marginStart="@dimen/global_actions_side_margin" - > - <LinearLayout - android:id="@android:id/list" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="@dimen/global_actions_grid_vertical_padding" - android:paddingBottom="@dimen/global_actions_grid_vertical_padding" - android:orientation="horizontal" - android:gravity="left | center_vertical" - android:translationZ="@dimen/global_actions_translate" - > - <RelativeLayout - android:id="@+id/global_actions_overflow_button" - android:contentDescription="@string/accessibility_menu" - android:layout_width="48dp" - android:layout_height="48dp" - > - <ImageView - android:src="@drawable/ic_more_vert" - android:layout_centerInParent="true" - android:layout_width="24dp" - android:layout_height="24dp" - android:tint="@color/control_more_vert" - /> - </RelativeLayout> - </LinearLayout> - </com.android.systemui.globalactions.GlobalActionsFlatLayout> - <androidx.constraintlayout.widget.ConstraintLayout - android:id="@+id/global_actions_lock_message_container" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone"> - <TextView - android:id="@+id/global_actions_lock_message" - style="@style/TextAppearance.Control.Title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginHorizontal="@dimen/global_actions_side_margin" - android:drawablePadding="12dp" - android:gravity="center" - android:text="@string/global_action_lock_message" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintVertical_bias="0.35"/> - </androidx.constraintlayout.widget.ConstraintLayout> + <include layout="@layout/global_actions_view" /> + + <include layout="@layout/global_actions_lock_view" /> <com.android.systemui.globalactions.MinHeightScrollView android:layout_width="match_parent" diff --git a/packages/SystemUI/res/layout/global_actions_lock_view.xml b/packages/SystemUI/res/layout/global_actions_lock_view.xml new file mode 100644 index 000000000000..eccc63688065 --- /dev/null +++ b/packages/SystemUI/res/layout/global_actions_lock_view.xml @@ -0,0 +1,35 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/global_actions_lock_message_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:visibility="gone"> + <TextView + android:id="@+id/global_actions_lock_message" + style="@style/TextAppearance.Control.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/global_actions_side_margin" + android:drawablePadding="12dp" + android:gravity="center" + android:text="@string/global_action_lock_message" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.35"/> +</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/global_actions_view.xml b/packages/SystemUI/res/layout/global_actions_view.xml new file mode 100644 index 000000000000..454707bc44e2 --- /dev/null +++ b/packages/SystemUI/res/layout/global_actions_view.xml @@ -0,0 +1,52 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<com.android.systemui.globalactions.GlobalActionsFlatLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@id/global_actions_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:theme="@style/qs_theme" + android:clipChildren="false" + android:clipToPadding="false" + android:layout_marginStart="@dimen/global_actions_side_margin" + > + <LinearLayout + android:id="@android:id/list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="@dimen/global_actions_grid_vertical_padding" + android:paddingBottom="@dimen/global_actions_grid_vertical_padding" + android:orientation="horizontal" + android:gravity="left | center_vertical" + android:translationZ="@dimen/global_actions_translate" + > + <RelativeLayout + android:id="@+id/global_actions_overflow_button" + android:contentDescription="@string/accessibility_menu" + android:layout_width="48dp" + android:layout_height="48dp" + > + <ImageView + android:src="@drawable/ic_more_vert" + android:layout_centerInParent="true" + android:layout_width="24dp" + android:layout_height="24dp" + android:tint="@color/control_more_vert" + /> + </RelativeLayout> + </LinearLayout> +</com.android.systemui.globalactions.GlobalActionsFlatLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 880dd378e390..01b55b70d5ad 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -357,9 +357,6 @@ the notification is not swiped enough to dismiss it. --> <bool name="config_showNotificationGear">true</bool> - <!-- Whether or not a background should be drawn behind a notification. --> - <bool name="config_drawNotificationBackground">true</bool> - <!-- Whether or the notifications can be shown and dismissed with a drag. --> <bool name="config_enableNotificationShadeDrag">true</bool> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java index a32cd1420fdc..3cbab8e66fdb 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java @@ -244,7 +244,7 @@ public class KeyguardSliceView extends LinearLayout { iconDrawable.setBounds(0, 0, Math.max(width, 1), iconSize); } } - button.setCompoundDrawables(iconDrawable, null, null, null); + button.setCompoundDrawablesRelative(iconDrawable, null, null, null); button.setOnClickListener(mOnClickListener); button.setClickable(pendingIntent != null); } @@ -536,9 +536,9 @@ public class KeyguardSliceView extends LinearLayout { } @Override - public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, + public void setCompoundDrawablesRelative(Drawable start, Drawable top, Drawable end, Drawable bottom) { - super.setCompoundDrawables(left, top, right, bottom); + super.setCompoundDrawablesRelative(start, top, end, bottom); updateDrawableColors(); updatePadding(); } @@ -558,9 +558,9 @@ public class KeyguardSliceView extends LinearLayout { public void setLockScreenMode(int mode) { mLockScreenMode = mode; if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) { - setGravity(Gravity.START); + setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); } else { - setGravity(Gravity.CENTER); + setTextAlignment(View.TEXT_ALIGNMENT_CENTER); } updatePadding(); } diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index 6151ac7a242b..3852b24fe4b3 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -327,8 +327,8 @@ public class SwipeHelper implements Gefingerpoken { if (Math.abs(delta) > pagingTouchSlop && Math.abs(delta) > Math.abs(deltaPerpendicular)) { if (mCallback.canChildBeDragged(mTouchedView)) { - mCallback.onBeginDrag(mTouchedView); mIsSwiping = true; + mCallback.onBeginDrag(mTouchedView); mInitialTouchPos = getPos(ev); mTranslation = getTranslation(mTouchedView); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java index f6b8b4c92049..70a57cc8bd2a 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java @@ -185,8 +185,12 @@ public class BrightLineFalsingManager implements FalsingManager { return true; } - // TODO(b/172655679): we always reject single-taps when doing a robust check for now. - return robustCheck; + // TODO(b/172655679): More heuristics to come. For now, allow touches through if face-authed + if (robustCheck) { + return !mDataProvider.isJustUnlockedWithFace(); + } + + return false; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java index 885048df13f1..ac3b6d26fab6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java @@ -82,9 +82,6 @@ public class AmbientState { private ExpandableNotificationRow mTrackedHeadsUpRow; private float mAppearFraction; - /** Tracks the state from AlertingNotificationManager#hasNotifications() */ - private boolean mHasAlertEntries; - public AmbientState( Context context, @NonNull SectionProvider sectionProvider) { @@ -368,21 +365,10 @@ public class AmbientState { mPanelTracking = panelTracking; } - public boolean hasPulsingNotifications() { - return mPulsing && mHasAlertEntries; - } - public void setPulsing(boolean hasPulsing) { mPulsing = hasPulsing; } - /** - * @return if we're pulsing in general - */ - public boolean isPulsing() { - return mPulsing; - } - public boolean isPulsing(NotificationEntry entry) { return mPulsing && entry.isAlerting(); } @@ -541,8 +527,4 @@ public class AmbientState { public float getAppearFraction() { return mAppearFraction; } - - public void setHasAlertEntries(boolean hasAlertEntries) { - mHasAlertEntries = hasAlertEntries; - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java index 1131a65abe93..ba03a50b0ba5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java @@ -31,175 +31,22 @@ import com.android.systemui.statusbar.notification.ShadeViewRefactor; import com.android.systemui.statusbar.notification.row.ExpandableView; /** - * Represents the bounds of a section of the notification shade and handles animation when the - * bounds change. + * Represents the priority of a notification section and tracks first and last visible children. */ public class NotificationSection { private @PriorityBucket int mBucket; - private View mOwningView; - private Rect mBounds = new Rect(); - private Rect mCurrentBounds = new Rect(-1, -1, -1, -1); - private Rect mStartAnimationRect = new Rect(); - private Rect mEndAnimationRect = new Rect(); - private ObjectAnimator mTopAnimator = null; - private ObjectAnimator mBottomAnimator = null; private ExpandableView mFirstVisibleChild; private ExpandableView mLastVisibleChild; - NotificationSection(View owningView, @PriorityBucket int bucket) { - mOwningView = owningView; + NotificationSection(@PriorityBucket int bucket) { mBucket = bucket; } - public void cancelAnimators() { - if (mBottomAnimator != null) { - mBottomAnimator.cancel(); - } - if (mTopAnimator != null) { - mTopAnimator.cancel(); - } - } - - public Rect getCurrentBounds() { - return mCurrentBounds; - } - - public Rect getBounds() { - return mBounds; - } - - public boolean didBoundsChange() { - return !mCurrentBounds.equals(mBounds); - } - - public boolean areBoundsAnimating() { - return mBottomAnimator != null || mTopAnimator != null; - } - @PriorityBucket public int getBucket() { return mBucket; } - public void startBackgroundAnimation(boolean animateTop, boolean animateBottom) { - // Left and right bounds are always applied immediately. - mCurrentBounds.left = mBounds.left; - mCurrentBounds.right = mBounds.right; - startBottomAnimation(animateBottom); - startTopAnimation(animateTop); - } - - - @ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.STATE_RESOLVER) - private void startTopAnimation(boolean animate) { - int previousEndValue = mEndAnimationRect.top; - int newEndValue = mBounds.top; - ObjectAnimator previousAnimator = mTopAnimator; - if (previousAnimator != null && previousEndValue == newEndValue) { - return; - } - if (!animate) { - // just a local update was performed - if (previousAnimator != null) { - // we need to increase all animation keyframes of the previous animator by the - // relative change to the end value - int previousStartValue = mStartAnimationRect.top; - PropertyValuesHolder[] values = previousAnimator.getValues(); - values[0].setIntValues(previousStartValue, newEndValue); - mStartAnimationRect.top = previousStartValue; - mEndAnimationRect.top = newEndValue; - previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime()); - return; - } else { - // no new animation needed, let's just apply the value - setBackgroundTop(newEndValue); - return; - } - } - if (previousAnimator != null) { - previousAnimator.cancel(); - } - ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundTop", - mCurrentBounds.top, newEndValue); - Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN; - animator.setInterpolator(interpolator); - animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); - // remove the tag when the animation is finished - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mStartAnimationRect.top = -1; - mEndAnimationRect.top = -1; - mTopAnimator = null; - } - }); - animator.start(); - mStartAnimationRect.top = mCurrentBounds.top; - mEndAnimationRect.top = newEndValue; - mTopAnimator = animator; - } - - @ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.STATE_RESOLVER) - private void startBottomAnimation(boolean animate) { - int previousStartValue = mStartAnimationRect.bottom; - int previousEndValue = mEndAnimationRect.bottom; - int newEndValue = mBounds.bottom; - ObjectAnimator previousAnimator = mBottomAnimator; - if (previousAnimator != null && previousEndValue == newEndValue) { - return; - } - if (!animate) { - // just a local update was performed - if (previousAnimator != null) { - // we need to increase all animation keyframes of the previous animator by the - // relative change to the end value - PropertyValuesHolder[] values = previousAnimator.getValues(); - values[0].setIntValues(previousStartValue, newEndValue); - mStartAnimationRect.bottom = previousStartValue; - mEndAnimationRect.bottom = newEndValue; - previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime()); - return; - } else { - // no new animation needed, let's just apply the value - setBackgroundBottom(newEndValue); - return; - } - } - if (previousAnimator != null) { - previousAnimator.cancel(); - } - ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundBottom", - mCurrentBounds.bottom, newEndValue); - Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN; - animator.setInterpolator(interpolator); - animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); - // remove the tag when the animation is finished - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mStartAnimationRect.bottom = -1; - mEndAnimationRect.bottom = -1; - mBottomAnimator = null; - } - }); - animator.start(); - mStartAnimationRect.bottom = mCurrentBounds.bottom; - mEndAnimationRect.bottom = newEndValue; - mBottomAnimator = animator; - } - - @ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.SHADE_VIEW) - private void setBackgroundTop(int top) { - mCurrentBounds.top = top; - mOwningView.invalidate(); - } - - @ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.SHADE_VIEW) - private void setBackgroundBottom(int bottom) { - mCurrentBounds.bottom = bottom; - mOwningView.invalidate(); - } - public ExpandableView getFirstVisibleChild() { return mFirstVisibleChild; } @@ -219,93 +66,4 @@ public class NotificationSection { mLastVisibleChild = child; return changed; } - - public void resetCurrentBounds() { - mCurrentBounds.set(mBounds); - } - - /** - * Returns true if {@code top} is equal to the top of this section (if not currently animating) - * or where the top of this section will be when animation completes. - */ - public boolean isTargetTop(int top) { - return (mTopAnimator == null && mCurrentBounds.top == top) - || (mTopAnimator != null && mEndAnimationRect.top == top); - } - - /** - * Returns true if {@code bottom} is equal to the bottom of this section (if not currently - * animating) or where the bottom of this section will be when animation completes. - */ - public boolean isTargetBottom(int bottom) { - return (mBottomAnimator == null && mCurrentBounds.bottom == bottom) - || (mBottomAnimator != null && mEndAnimationRect.bottom == bottom); - } - - /** - * Update the bounds of this section based on it's views - * - * @param minTopPosition the minimum position that the top needs to have - * @param minBottomPosition the minimum position that the bottom needs to have - * @return the position of the new bottom - */ - public int updateBounds(int minTopPosition, int minBottomPosition, - boolean shiftBackgroundWithFirst) { - int top = minTopPosition; - int bottom = minTopPosition; - ExpandableView firstView = getFirstVisibleChild(); - if (firstView != null) { - // Round Y up to avoid seeing the background during animation - int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView)); - // TODO: look into the already animating part - int newTop; - if (isTargetTop(finalTranslationY)) { - // we're ending up at the same location as we are now, let's just skip the - // animation - newTop = finalTranslationY; - } else { - newTop = (int) Math.ceil(firstView.getTranslationY()); - } - top = Math.max(newTop, top); - if (firstView.showingPulsing()) { - // If we're pulsing, the notification can actually go below! - bottom = Math.max(bottom, finalTranslationY - + ExpandableViewState.getFinalActualHeight(firstView)); - if (shiftBackgroundWithFirst) { - mBounds.left += Math.max(firstView.getTranslation(), 0); - mBounds.right += Math.min(firstView.getTranslation(), 0); - } - } - } - top = Math.max(minTopPosition, top); - ExpandableView lastView = getLastVisibleChild(); - if (lastView != null) { - float finalTranslationY = ViewState.getFinalTranslationY(lastView); - int finalHeight = ExpandableViewState.getFinalActualHeight(lastView); - // Round Y down to avoid seeing the background during animation - int finalBottom = (int) Math.floor( - finalTranslationY + finalHeight - lastView.getClipBottomAmount()); - int newBottom; - if (isTargetBottom(finalBottom)) { - // we're ending up at the same location as we are now, lets just skip the animation - newBottom = finalBottom; - } else { - newBottom = (int) (lastView.getTranslationY() + lastView.getActualHeight() - - lastView.getClipBottomAmount()); - // The background can never be lower than the end of the last view - minBottomPosition = (int) Math.min( - lastView.getTranslationY() + lastView.getActualHeight(), - minBottomPosition); - } - bottom = Math.max(bottom, Math.max(newBottom, minBottomPosition)); - } - bottom = Math.max(top, bottom); - mBounds.top = top; - mBounds.bottom = bottom; - return bottom; - } - - public boolean needsBackground() { - return mFirstVisibleChild != null && mBucket != BUCKET_MEDIA_CONTROLS; - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt index 4f7e14ba4a4c..36c5419b7399 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt @@ -126,7 +126,7 @@ class NotificationSectionsManager @Inject internal constructor( fun createSectionsForBuckets(): Array<NotificationSection> = sectionsFeatureManager.getNotificationBuckets() - .map { NotificationSection(parent, it) } + .map { NotificationSection(it) } .toTypedArray() /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 742e517e71e7..ba5f95e9c4d8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -38,12 +38,9 @@ import android.content.Intent; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PointF; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.os.Bundle; import android.os.UserHandle; @@ -73,7 +70,6 @@ import android.widget.OverScroller; import android.widget.ScrollView; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.graphics.ColorUtils; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.keyguard.KeyguardSliceView; @@ -158,8 +154,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private ExpandHelper mExpandHelper; private NotificationSwipeHelper mSwipeHelper; private int mCurrentStackHeight = Integer.MAX_VALUE; - private final Paint mBackgroundPaint = new Paint(); - private final boolean mShouldDrawNotificationBackground; private boolean mHighPriorityBeforeSpeedBump; private boolean mDismissRtl; @@ -258,7 +252,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable protected FooterView mFooterView; protected EmptyShadeView mEmptyShadeView; private boolean mDismissAllInProgress; - private boolean mFadeNotificationsOnDismiss; private FooterDismissListener mFooterDismissListener; private boolean mFlingAfterUpEvent; @@ -328,10 +321,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } }; private NotificationSection[] mSections; - private boolean mAnimateNextBackgroundTop; - private boolean mAnimateNextBackgroundBottom; - private boolean mAnimateNextSectionBoundsChange; - private int mBgColor; private float mDimAmount; private ValueAnimator mDimAnimator; private ArrayList<ExpandableView> mTmpSortedChildren = new ArrayList<>(); @@ -342,25 +331,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } }; private ValueAnimator.AnimatorUpdateListener mDimUpdateListener - = new ValueAnimator.AnimatorUpdateListener() { - - @Override - public void onAnimationUpdate(ValueAnimator animation) { - setDimAmount((Float) animation.getAnimatedValue()); - } - }; + = animation -> setDimAmount((Float) animation.getAnimatedValue()); protected ViewGroup mQsContainer; private boolean mContinuousShadowUpdate; - private boolean mContinuousBackgroundUpdate; private ViewTreeObserver.OnPreDrawListener mShadowUpdater = () -> { updateViewShadows(); return true; }; - private ViewTreeObserver.OnPreDrawListener mBackgroundUpdater = () -> { - updateBackground(); - return true; - }; private Comparator<ExpandableView> mViewPositionComparator = (view, otherView) -> { float endY = view.getTranslationY() + view.getActualHeight(); float otherEndY = otherView.getTranslationY() + otherView.getActualHeight(); @@ -379,7 +357,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (mAmbientState.isHiddenAtAll()) { float xProgress = mHideXInterpolator.getInterpolation( (1 - mLinearHideAmount) * mBackgroundXFactor); - outline.setRoundRect(mBackgroundAnimationRect, + outline.setRoundRect(mOutlineAnimationRect, MathUtils.lerp(mCornerRadius / 2.0f, mCornerRadius, xProgress)); outline.setAlpha(1.0f - mAmbientState.getHideAmount()); @@ -388,7 +366,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } }; - private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC); private boolean mPulsing; private boolean mScrollable; private View mForcedScroll; @@ -422,7 +399,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private boolean mInHeadsUpPinnedMode; private boolean mHeadsUpAnimatingAway; private int mStatusBarState; - private int mCachedBackgroundColor; private boolean mHeadsUpGoingAwayAnimationsAllowed = true; private Runnable mReflingAndAnimateScroll = () -> { if (ANCHOR_SCROLLING) { @@ -432,7 +408,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable }; private int mCornerRadius; private int mSidePaddings; - private final Rect mBackgroundAnimationRect = new Rect(); + private final Rect mOutlineAnimationRect = new Rect(); private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>(); private int mHeadsUpInset; private HeadsUpAppearanceController mHeadsUpAppearanceController; @@ -452,7 +428,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private final NotificationSectionsManager mSectionsManager; private ForegroundServiceDungeonView mFgsSectionView; - private boolean mAnimateBottomOnLayout; private float mLastSentAppear; private float mLastSentExpandedHeight; private boolean mWillExpand; @@ -463,7 +438,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private boolean mKeyguardMediaControllorVisible; private NotificationEntry mTopHeadsUpEntry; - private long mNumHeadsUp; private NotificationStackScrollLayoutController.TouchHandler mTouchHandler; private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener = @@ -530,7 +504,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mSections = mSectionsManager.createSectionsForBuckets(); mAmbientState = new AmbientState(context, mSectionsManager); - mBgColor = context.getColor(R.color.notification_shade_background_color); int minHeight = res.getDimensionPixelSize(R.dimen.notification_min_height); int maxHeight = res.getDimensionPixelSize(R.dimen.notification_max_height); mExpandHelper = new ExpandHelper(getContext(), mExpandHelperCallback, @@ -539,13 +512,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mExpandHelper.setScrollAdapter(mScrollAdapter); mStackScrollAlgorithm = createStackScrollAlgorithm(context); - mShouldDrawNotificationBackground = - res.getBoolean(R.bool.config_drawNotificationBackground); setOutlineProvider(mOutlineProvider); - boolean willDraw = mShouldDrawNotificationBackground || DEBUG; - setWillNotDraw(!willDraw); - mBackgroundPaint.setAntiAlias(true); + setWillNotDraw(!DEBUG); if (DEBUG) { mDebugPaint = new Paint(); mDebugPaint.setColor(0xffff0000); @@ -590,7 +559,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * @return the height at which we will wake up when pulsing */ public float getWakeUpHeight() { - ExpandableView firstChild = getFirstChildWithBackground(); + ExpandableView firstChild = getFirstExpandableView(); if (firstChild != null) { if (mKeyguardBypassEnabledProvider.getBypassEnabled()) { return firstChild.getHeadsUpHeightWithoutHeader(); @@ -641,22 +610,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } void updateBgColor() { - mBgColor = mContext.getColor(R.color.notification_shade_background_color); - updateBackgroundDimming(); mShelf.onUiModeChanged(); } @ShadeViewRefactor(RefactorComponent.DECORATOR) protected void onDraw(Canvas canvas) { - if (mShouldDrawNotificationBackground - && (mSections[0].getCurrentBounds().top - < mSections[mSections.length - 1].getCurrentBounds().bottom - || mAmbientState.isDozing())) { - drawBackground(canvas); - } else if (mInHeadsUpPinnedMode || mHeadsUpAnimatingAway) { - drawHeadsUpBackground(canvas); - } - if (DEBUG) { int y = mTopPadding; canvas.drawLine(0, y, getWidth(), y, mDebugPaint); @@ -691,160 +649,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } - @ShadeViewRefactor(RefactorComponent.DECORATOR) - private void drawBackground(Canvas canvas) { - int lockScreenLeft = mSidePaddings; - int lockScreenRight = getWidth() - mSidePaddings; - int lockScreenTop = mSections[0].getCurrentBounds().top; - int lockScreenBottom = mSections[mSections.length - 1].getCurrentBounds().bottom; - int hiddenLeft = getWidth() / 2; - int hiddenTop = mTopPadding; - - float yProgress = 1 - mInterpolatedHideAmount; - float xProgress = mHideXInterpolator.getInterpolation( - (1 - mLinearHideAmount) * mBackgroundXFactor); - - int left = (int) MathUtils.lerp(hiddenLeft, lockScreenLeft, xProgress); - int right = (int) MathUtils.lerp(hiddenLeft, lockScreenRight, xProgress); - int top = (int) MathUtils.lerp(hiddenTop, lockScreenTop, yProgress); - int bottom = (int) MathUtils.lerp(hiddenTop, lockScreenBottom, yProgress); - mBackgroundAnimationRect.set( - left, - top, - right, - bottom); - - int backgroundTopAnimationOffset = top - lockScreenTop; - // TODO(kprevas): this may not be necessary any more since we don't display the shelf in AOD - boolean anySectionHasVisibleChild = false; - for (NotificationSection section : mSections) { - if (section.needsBackground()) { - anySectionHasVisibleChild = true; - break; - } - } - boolean shouldDrawBackground; - if (mKeyguardBypassEnabledProvider.getBypassEnabled() && onKeyguard()) { - shouldDrawBackground = isPulseExpanding(); - } else { - shouldDrawBackground = !mAmbientState.isDozing() || anySectionHasVisibleChild; - } - if (shouldDrawBackground) { - drawBackgroundRects(canvas, left, right, top, backgroundTopAnimationOffset); - } - - updateClipping(); - } - - /** - * Draws round rects for each background section. - * - * We want to draw a round rect for each background section as defined by {@link #mSections}. - * However, if two sections are directly adjacent with no gap between them (e.g. on the - * lockscreen where the shelf can appear directly below the high priority section, or while - * scrolling the shade so that the top of the shelf is right at the bottom of the high priority - * section), we don't want to round the adjacent corners. - * - * Since {@link Canvas} doesn't provide a way to draw a half-rounded rect, this means that we - * need to coalesce the backgrounds for adjacent sections and draw them as a single round rect. - * This method tracks the top of each rect we need to draw, then iterates through the visible - * sections. If a section is not adjacent to the previous section, we draw the previous rect - * behind the sections we've accumulated up to that point, then start a new rect at the top of - * the current section. When we're done iterating we will always have one rect left to draw. - */ - private void drawBackgroundRects(Canvas canvas, int left, int right, int top, - int animationYOffset) { - int backgroundRectTop = top; - int lastSectionBottom = - mSections[0].getCurrentBounds().bottom + animationYOffset; - int currentLeft = left; - int currentRight = right; - boolean first = true; - for (NotificationSection section : mSections) { - if (!section.needsBackground()) { - continue; - } - int sectionTop = section.getCurrentBounds().top + animationYOffset; - int ownLeft = Math.min(Math.max(left, section.getCurrentBounds().left), right); - int ownRight = Math.max(Math.min(right, section.getCurrentBounds().right), ownLeft); - // If sections are directly adjacent to each other, we don't want to draw them - // as separate roundrects, as the rounded corners right next to each other look - // bad. - if (sectionTop - lastSectionBottom > DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX - || ((currentLeft != ownLeft || currentRight != ownRight) && !first)) { - canvas.drawRoundRect(currentLeft, - backgroundRectTop, - currentRight, - lastSectionBottom, - mCornerRadius, mCornerRadius, mBackgroundPaint); - backgroundRectTop = sectionTop; - } - currentLeft = ownLeft; - currentRight = ownRight; - lastSectionBottom = - section.getCurrentBounds().bottom + animationYOffset; - first = false; - } - canvas.drawRoundRect(currentLeft, - backgroundRectTop, - currentRight, - lastSectionBottom, - mCornerRadius, mCornerRadius, mBackgroundPaint); - } - - private void drawHeadsUpBackground(Canvas canvas) { - int left = mSidePaddings; - int right = getWidth() - mSidePaddings; - - float top = getHeight(); - float bottom = 0; - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - if (child.getVisibility() != View.GONE - && child instanceof ExpandableNotificationRow) { - ExpandableNotificationRow row = (ExpandableNotificationRow) child; - if ((row.isPinned() || row.isHeadsUpAnimatingAway()) && row.getTranslation() < 0 - && row.getProvider().shouldShowGutsOnSnapOpen()) { - top = Math.min(top, row.getTranslationY()); - bottom = Math.max(bottom, row.getTranslationY() + row.getActualHeight()); - } - } - } - - if (top < bottom) { - canvas.drawRoundRect( - left, top, right, bottom, - mCornerRadius, mCornerRadius, mBackgroundPaint); - } - } - - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - void updateBackgroundDimming() { - // No need to update the background color if it's not being drawn. - if (!mShouldDrawNotificationBackground) { - return; - } - final boolean newFlowHideShelf = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* on by default */) == 1; - if (newFlowHideShelf) { - mBackgroundPaint.setColor(Color.TRANSPARENT); - invalidate(); - return; - } - // Interpolate between semi-transparent notification panel background color - // and white AOD separator. - float colorInterpolation = MathUtils.smoothStep(0.4f /* start */, 1f /* end */, - mLinearHideAmount); - int color = ColorUtils.blendARGB(mBgColor, Color.WHITE, colorInterpolation); - - if (mCachedBackgroundColor != color) { - mCachedBackgroundColor = color; - mBackgroundPaint.setColor(color); - invalidate(); - } - } - private void reinitView() { initView(getContext(), mKeyguardBypassEnabledProvider, mSwipeHelper); } @@ -979,7 +783,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable updateContentHeight(); clampScrollPosition(); requestChildrenUpdate(); - updateFirstAndLastBackgroundViews(); + updateFirstAndLastExpandableView(); updateAlgorithmLayoutMinHeight(); updateOwnTranslationZ(); } @@ -1050,9 +854,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private void onPreDrawDuringAnimation() { mShelf.updateAppearance(); updateClippingToTopRoundedCorner(); - if (!mNeedsAnimation && !mChildrenUpdateRequested) { - updateBackground(); - } } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @@ -2369,131 +2170,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private void updateBackground() { - // No need to update the background color if it's not being drawn. - if (!mShouldDrawNotificationBackground) { - return; - } - - updateBackgroundBounds(); - if (didSectionBoundsChange()) { - boolean animate = mAnimateNextSectionBoundsChange || mAnimateNextBackgroundTop - || mAnimateNextBackgroundBottom || areSectionBoundsAnimating(); - if (!isExpanded()) { - abortBackgroundAnimators(); - animate = false; - } - if (animate) { - startBackgroundAnimation(); - } else { - for (NotificationSection section : mSections) { - section.resetCurrentBounds(); - } - invalidate(); - } - } else { - abortBackgroundAnimators(); - } - mAnimateNextBackgroundTop = false; - mAnimateNextBackgroundBottom = false; - mAnimateNextSectionBoundsChange = false; - } - - @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) - private void abortBackgroundAnimators() { - for (NotificationSection section : mSections) { - section.cancelAnimators(); - } - } - - private boolean didSectionBoundsChange() { - for (NotificationSection section : mSections) { - if (section.didBoundsChange()) { - return true; - } - } - return false; - } - - @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) - private boolean areSectionBoundsAnimating() { - for (NotificationSection section : mSections) { - if (section.areBoundsAnimating()) { - return true; - } - } - return false; - } - - @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) - private void startBackgroundAnimation() { - // TODO(kprevas): do we still need separate fields for top/bottom? - // or can each section manage its own animation state? - NotificationSection firstVisibleSection = getFirstVisibleSection(); - NotificationSection lastVisibleSection = getLastVisibleSection(); - for (NotificationSection section : mSections) { - section.startBackgroundAnimation( - section == firstVisibleSection - ? mAnimateNextBackgroundTop - : mAnimateNextSectionBoundsChange, - section == lastVisibleSection - ? mAnimateNextBackgroundBottom - : mAnimateNextSectionBoundsChange); - } - } - - /** - * Update the background bounds to the new desired bounds - */ - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - private void updateBackgroundBounds() { - int left = mSidePaddings; - int right = getWidth() - mSidePaddings; - for (NotificationSection section : mSections) { - section.getBounds().left = left; - section.getBounds().right = right; - } - - if (!mIsExpanded) { - for (NotificationSection section : mSections) { - section.getBounds().top = 0; - section.getBounds().bottom = 0; - } - return; - } - int minTopPosition; - NotificationSection lastSection = getLastVisibleSection(); - boolean onKeyguard = mStatusBarState == StatusBarState.KEYGUARD; - if (!onKeyguard) { - minTopPosition = (int) (mTopPadding + mStackTranslation); - } else if (lastSection == null) { - minTopPosition = mTopPadding; - } else { - // The first sections could be empty while there could still be elements in later - // sections. The position of these first few sections is determined by the position of - // the first visible section. - NotificationSection firstVisibleSection = getFirstVisibleSection(); - firstVisibleSection.updateBounds(0 /* minTopPosition*/, 0 /* minBottomPosition */, - false /* shiftPulsingWithFirst */); - minTopPosition = firstVisibleSection.getBounds().top; - } - boolean shiftPulsingWithFirst = mNumHeadsUp <= 1 - && (mAmbientState.isDozing() - || (mKeyguardBypassEnabledProvider.getBypassEnabled() && onKeyguard)); - for (NotificationSection section : mSections) { - int minBottomPosition = minTopPosition; - if (section == lastSection) { - // We need to make sure the section goes all the way to the shelf - minBottomPosition = (int) (ViewState.getFinalTranslationY(mShelf) - + mShelf.getIntrinsicHeight()); - } - minTopPosition = section.updateBounds(minTopPosition, minBottomPosition, - shiftPulsingWithFirst); - shiftPulsingWithFirst = false; - } - } - private NotificationSection getFirstVisibleSection() { for (NotificationSection section : mSections) { if (section.getFirstVisibleChild() != null) { @@ -2514,7 +2190,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } @ShadeViewRefactor(RefactorComponent.COORDINATOR) - private ExpandableView getLastChildWithBackground() { + private ExpandableView getLastExpandableView() { int childCount = getChildCount(); for (int i = childCount - 1; i >= 0; i--) { ExpandableView child = (ExpandableView) getChildAt(i); @@ -2527,7 +2203,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } @ShadeViewRefactor(RefactorComponent.COORDINATOR) - private ExpandableView getFirstChildWithBackground() { + private ExpandableView getFirstExpandableView() { int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { ExpandableView child = (ExpandableView) getChildAt(i); @@ -2540,7 +2216,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } //TODO: We shouldn't have to generate this list every time - private List<ExpandableView> getChildrenWithBackground() { + private List<ExpandableView> getExpandableViewList() { ArrayList<ExpandableView> children = new ArrayList<>(); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -3078,32 +2754,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) - private void updateFirstAndLastBackgroundViews() { - NotificationSection firstSection = getFirstVisibleSection(); - NotificationSection lastSection = getLastVisibleSection(); - ExpandableView previousFirstChild = - firstSection == null ? null : firstSection.getFirstVisibleChild(); - ExpandableView previousLastChild = - lastSection == null ? null : lastSection.getLastVisibleChild(); - - ExpandableView firstChild = getFirstChildWithBackground(); - ExpandableView lastChild = getLastChildWithBackground(); - boolean sectionViewsChanged = mSectionsManager.updateFirstAndLastViewsForAllSections( - mSections, getChildrenWithBackground()); - - if (mAnimationsEnabled && mIsExpanded) { - mAnimateNextBackgroundTop = firstChild != previousFirstChild; - mAnimateNextBackgroundBottom = lastChild != previousLastChild || mAnimateBottomOnLayout; - mAnimateNextSectionBoundsChange = sectionViewsChanged; - } else { - mAnimateNextBackgroundTop = false; - mAnimateNextBackgroundBottom = false; - mAnimateNextSectionBoundsChange = false; - } + private void updateFirstAndLastExpandableView() { + ExpandableView lastChild = getLastExpandableView(); + mSectionsManager.updateFirstAndLastViewsForAllSections( + mSections, getExpandableViewList()); mAmbientState.setLastVisibleBackgroundChild(lastChild); // TODO: Refactor SectionManager and put the RoundnessManager there. mController.getNoticationRoundessManager().updateRoundedChildren(mSections); - mAnimateBottomOnLayout = false; invalidate(); } @@ -3265,7 +2922,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable setAnimationRunning(true); mStateAnimator.startAnimationForEvents(mAnimationEvents, mGoToFullShadeDelay); mAnimationEvents.clear(); - updateBackground(); updateViewShadows(); updateClippingToTopRoundedCorner(); } else { @@ -4350,7 +4006,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) private void setDimAmount(float dimAmount) { mDimAmount = dimAmount; - updateBackgroundDimming(); } @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) @@ -4419,7 +4074,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } runAnimationFinishedRunnables(); setAnimationRunning(false); - updateBackground(); updateViewShadows(); updateClippingToTopRoundedCorner(); } @@ -4554,7 +4208,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable invalidateOutline(); } updateAlgorithmHeightAndPadding(); - updateBackgroundDimming(); requestChildrenUpdate(); updateOwnTranslationZ(); } @@ -5435,7 +5088,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ public void setDozeAmount(float dozeAmount) { mAmbientState.setDozeAmount(dozeAmount); - updateContinuousBackgroundDrawing(); requestChildrenUpdate(); } @@ -5473,7 +5125,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } void setAnimateBottomOnLayout(boolean animateBottomOnLayout) { - mAnimateBottomOnLayout = animateBottomOnLayout; } public void setOnPulseHeightChangedListener(Runnable listener) { @@ -5506,25 +5157,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable void onSwipeBegin() { requestDisallowInterceptTouchEvent(true); - updateFirstAndLastBackgroundViews(); updateContinuousShadowDrawing(); - updateContinuousBackgroundDrawing(); requestChildrenUpdate(); } - void onSwipeEnd() { - updateFirstAndLastBackgroundViews(); - } - void setTopHeadsUpEntry(NotificationEntry topEntry) { mTopHeadsUpEntry = topEntry; } - void setNumHeadsUp(long numHeadsUp) { - mNumHeadsUp = numHeadsUp; - mAmbientState.setHasAlertEntries(numHeadsUp > 0); - } - public boolean getIsExpanded() { return mIsExpanded; } @@ -5639,27 +5279,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mSectionsManager.updateSectionBoundaries(reason); } - boolean isSilkDismissEnabled() { - return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* enabled by default */) == 1; - } - - void updateContinuousBackgroundDrawing() { - if (isSilkDismissEnabled()) { - return; - } - boolean continuousBackground = !mAmbientState.isFullyAwake() - && mSwipeHelper.isSwiping(); - if (continuousBackground != mContinuousBackgroundUpdate) { - mContinuousBackgroundUpdate = continuousBackground; - if (continuousBackground) { - getViewTreeObserver().addOnPreDrawListener(mBackgroundUpdater); - } else { - getViewTreeObserver().removeOnPreDrawListener(mBackgroundUpdater); - } - } - } - @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) void updateContinuousShadowDrawing() { boolean continuousShadowUpdate = mAnimationRunning diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 9d4665a5eeca..abbbbb8352f5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -394,7 +394,6 @@ public class NotificationStackScrollLayoutController { if (mView.getDismissAllInProgress()) { return; } - mView.onSwipeEnd(); if (view instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) view; if (row.isHeadsUp()) { @@ -454,7 +453,6 @@ public class NotificationStackScrollLayoutController { @Override public void onChildSnappedBack(View animView, float targetLeft) { - mView.onSwipeEnd(); if (animView instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) animView; if (row.isPinned() && !canChildBeDismissed(row) @@ -518,9 +516,7 @@ public class NotificationStackScrollLayoutController { @Override public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) { - long numEntries = mHeadsUpManager.getAllEntries().count(); NotificationEntry topEntry = mHeadsUpManager.getTopEntry(); - mView.setNumHeadsUp(numEntries); mView.setTopHeadsUpEntry(topEntry); mNotificationRoundnessManager.updateView(entry.getRow(), false /* animate */); } @@ -665,8 +661,6 @@ public class NotificationStackScrollLayoutController { mHeadsUpManager.setAnimationStateHandler(mView::setHeadsUpGoingAwayAnimationsAllowed); mDynamicPrivacyController.addListener(mDynamicPrivacyControllerListener); - mScrimController.setScrimBehindChangeRunnable(mView::updateBackgroundDimming); - mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener); mFadeNotificationsOnDismiss = // TODO: this should probably be injected directly diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2fe37d48379b..e8ee18c6f4d4 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2771,6 +2771,7 @@ public class ConnectivityService extends IConnectivityManager.Stub networkCapabilities = new NetworkCapabilities(networkCapabilities); networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid); } + processCapabilitiesFromAgent(nai, networkCapabilities); updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities); break; } @@ -2809,6 +2810,31 @@ public class ConnectivityService extends IConnectivityManager.Stub mKeepaliveTracker.handleEventSocketKeepalive(nai, msg); break; } + case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: { + if (!nai.supportsUnderlyingNetworks()) { + Log.wtf(TAG, "Non-virtual networks cannot have underlying networks"); + break; + } + final ArrayList<Network> underlying; + try { + underlying = ((Bundle) msg.obj).getParcelableArrayList( + NetworkAgent.UNDERLYING_NETWORKS_KEY); + } catch (NullPointerException | ClassCastException e) { + break; + } + final Network[] oldUnderlying = nai.declaredUnderlyingNetworks; + nai.declaredUnderlyingNetworks = (underlying != null) + ? underlying.toArray(new Network[0]) : null; + + if (!Arrays.equals(oldUnderlying, nai.declaredUnderlyingNetworks)) { + if (DBG) { + log(nai.toShortString() + " changed underlying networks to " + + Arrays.toString(nai.declaredUnderlyingNetworks)); + } + updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); + notifyIfacesChangedForNetworkStats(); + } + } } } @@ -3394,7 +3420,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } mLegacyTypeTracker.remove(nai, wasDefault); if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) { - updateAllVpnsCapabilities(); + propagateUnderlyingNetworkCapabilities(); } rematchAllNetworksAndRequests(); mLingerMonitor.noteDisconnect(nai); @@ -4704,10 +4730,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (mLockdownEnabled) { return new VpnInfo[0]; } - List<VpnInfo> infoList = new ArrayList<>(); - for (int i = 0; i < mVpns.size(); i++) { - VpnInfo info = createVpnInfo(mVpns.valueAt(i)); + for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { + VpnInfo info = createVpnInfo(nai); if (info != null) { infoList.add(info); } @@ -4720,13 +4745,10 @@ public class ConnectivityService extends IConnectivityManager.Stub * @return VPN information for accounting, or null if we can't retrieve all required * information, e.g underlying ifaces. */ - @Nullable - private VpnInfo createVpnInfo(Vpn vpn) { - VpnInfo info = vpn.getVpnInfo(); - if (info == null) { - return null; - } - Network[] underlyingNetworks = vpn.getUnderlyingNetworks(); + private VpnInfo createVpnInfo(NetworkAgentInfo nai) { + if (!nai.isVPN()) return null; + + Network[] underlyingNetworks = nai.declaredUnderlyingNetworks; // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret // the underlyingNetworks list. if (underlyingNetworks == null) { @@ -4735,23 +4757,33 @@ public class ConnectivityService extends IConnectivityManager.Stub underlyingNetworks = new Network[] { defaultNai.network }; } } - if (underlyingNetworks != null && underlyingNetworks.length > 0) { - List<String> interfaces = new ArrayList<>(); - for (Network network : underlyingNetworks) { - LinkProperties lp = getLinkProperties(network); - if (lp != null) { - for (String iface : lp.getAllInterfaceNames()) { - if (!TextUtils.isEmpty(iface)) { - interfaces.add(iface); - } - } + + if (ArrayUtils.isEmpty(underlyingNetworks)) return null; + + List<String> interfaces = new ArrayList<>(); + for (Network network : underlyingNetworks) { + NetworkAgentInfo underlyingNai = getNetworkAgentInfoForNetwork(network); + if (underlyingNai == null) continue; + LinkProperties lp = underlyingNai.linkProperties; + for (String iface : lp.getAllInterfaceNames()) { + if (!TextUtils.isEmpty(iface)) { + interfaces.add(iface); } } - if (!interfaces.isEmpty()) { - info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]); - } } - return info.underlyingIfaces == null ? null : info; + + if (interfaces.isEmpty()) return null; + + VpnInfo info = new VpnInfo(); + info.ownerUid = nai.networkCapabilities.getOwnerUid(); + info.vpnIface = nai.linkProperties.getInterfaceName(); + // Must be non-null or NetworkStatsService will crash. + // Cannot happen in production code because Vpn only registers the NetworkAgent after the + // tun or ipsec interface is created. + if (info.vpnIface == null) return null; + info.underlyingIfaces = interfaces.toArray(new String[0]); + + return info; } /** @@ -4774,33 +4806,19 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** - * Ask all VPN objects to recompute and update their capabilities. + * Ask all networks with underlying networks to recompute and update their capabilities. * - * When underlying networks change, VPNs may have to update capabilities to reflect things - * like the metered bit, their transports, and so on. This asks the VPN objects to update - * their capabilities, and as this will cause them to send messages to the ConnectivityService - * handler thread through their agent, this is asynchronous. When the capabilities objects - * are computed they will be up-to-date as they are computed synchronously from here and - * this is running on the ConnectivityService thread. + * When underlying networks change, such networks may have to update capabilities to reflect + * things like the metered bit, their transports, and so on. The capabilities are calculated + * immediately. This method runs on the ConnectivityService thread. */ - private void updateAllVpnsCapabilities() { - Network defaultNetwork = getNetwork(getDefaultNetwork()); - synchronized (mVpns) { - for (int i = 0; i < mVpns.size(); i++) { - final Vpn vpn = mVpns.valueAt(i); - NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork); - updateVpnCapabilities(vpn, nc); - } - } - } - - private void updateVpnCapabilities(Vpn vpn, @Nullable NetworkCapabilities nc) { + private void propagateUnderlyingNetworkCapabilities() { ensureRunningOnConnectivityServiceThread(); - NetworkAgentInfo vpnNai = getNetworkAgentInfoForNetId(vpn.getNetId()); - if (vpnNai == null || nc == null) { - return; + for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { + if (nai.supportsUnderlyingNetworks()) { + updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); + } } - updateCapabilities(vpnNai.getCurrentScore(), vpnNai, nc); } @Override @@ -5113,7 +5131,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void onUserStart(int userId) { + private void onUserStarted(int userId) { synchronized (mVpns) { Vpn userVpn = mVpns.get(userId); if (userVpn != null) { @@ -5128,7 +5146,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void onUserStop(int userId) { + private void onUserStopped(int userId) { synchronized (mVpns) { Vpn userVpn = mVpns.get(userId); if (userVpn == null) { @@ -5142,28 +5160,22 @@ public class ConnectivityService extends IConnectivityManager.Stub private void onUserAdded(int userId) { mPermissionMonitor.onUserAdded(userId); - Network defaultNetwork = getNetwork(getDefaultNetwork()); synchronized (mVpns) { final int vpnsSize = mVpns.size(); for (int i = 0; i < vpnsSize; i++) { Vpn vpn = mVpns.valueAt(i); vpn.onUserAdded(userId); - NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork); - updateVpnCapabilities(vpn, nc); } } } private void onUserRemoved(int userId) { mPermissionMonitor.onUserRemoved(userId); - Network defaultNetwork = getNetwork(getDefaultNetwork()); synchronized (mVpns) { final int vpnsSize = mVpns.size(); for (int i = 0; i < vpnsSize; i++) { Vpn vpn = mVpns.valueAt(i); vpn.onUserRemoved(userId); - NetworkCapabilities nc = vpn.updateCapabilities(defaultNetwork); - updateVpnCapabilities(vpn, nc); } } } @@ -5245,9 +5257,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (userId == UserHandle.USER_NULL) return; if (Intent.ACTION_USER_STARTED.equals(action)) { - onUserStart(userId); + onUserStarted(userId); } else if (Intent.ACTION_USER_STOPPED.equals(action)) { - onUserStop(userId); + onUserStopped(userId); } else if (Intent.ACTION_USER_ADDED.equals(action)) { onUserAdded(userId); } else if (Intent.ACTION_USER_REMOVED.equals(action)) { @@ -5959,13 +5971,29 @@ public class ConnectivityService extends IConnectivityManager.Stub int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS); + } else { + enforceNetworkFactoryPermission(); + } + + final int uid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + try { + return registerNetworkAgentInternal(messenger, networkInfo, linkProperties, + networkCapabilities, currentScore, networkAgentConfig, providerId, uid); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + private Network registerNetworkAgentInternal(Messenger messenger, NetworkInfo networkInfo, + LinkProperties linkProperties, NetworkCapabilities networkCapabilities, + int currentScore, NetworkAgentConfig networkAgentConfig, int providerId, int uid) { + if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { // Strictly, sanitizing here is unnecessary as the capabilities will be sanitized in // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never // sees capabilities that may be malicious, which might prevent mistakes in the future. networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(Binder.getCallingUid()); - } else { - enforceNetworkFactoryPermission(); + networkCapabilities.restrictCapabilitesForTestNetwork(uid); } LinkProperties lp = new LinkProperties(linkProperties); @@ -5976,9 +6004,10 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), - this, mNetd, mDnsResolver, mNMS, providerId, Binder.getCallingUid()); + this, mNetd, mDnsResolver, mNMS, providerId, uid); // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says. + processCapabilitiesFromAgent(nai, nc); nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); processLinkPropertiesFromAgent(nai, nai.linkProperties); @@ -5986,13 +6015,8 @@ public class ConnectivityService extends IConnectivityManager.Stub final String name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSsid() : extraInfo; if (DBG) log("registerNetworkAgent " + nai); - final long token = Binder.clearCallingIdentity(); - try { - mDeps.getNetworkStack().makeNetworkMonitor( - nai.network, name, new NetworkMonitorCallbacks(nai)); - } finally { - Binder.restoreCallingIdentity(token); - } + mDeps.getNetworkStack().makeNetworkMonitor( + nai.network, name, new NetworkMonitorCallbacks(nai)); // NetworkAgentInfo registration will finish when the NetworkMonitor is created. // If the network disconnects or sends any other event before that, messages are deferred by // NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the @@ -6019,6 +6043,12 @@ public class ConnectivityService extends IConnectivityManager.Stub updateUids(nai, null, nai.networkCapabilities); } + /** + * Called when receiving LinkProperties directly from a NetworkAgent. + * Stores into |nai| any data coming from the agent that might also be written to the network's + * LinkProperties by ConnectivityService itself. This ensures that the data provided by the + * agent is not lost when updateLinkProperties is called. + */ private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) { lp.ensureDirectlyConnectedRoutes(); nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix()); @@ -6315,6 +6345,30 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** + * Called when receiving NetworkCapabilities directly from a NetworkAgent. + * Stores into |nai| any data coming from the agent that might also be written to the network's + * NetworkCapabilities by ConnectivityService itself. This ensures that the data provided by the + * agent is not lost when updateCapabilities is called. + */ + private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) { + nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED); + } + + /** Propagates to |nc| the capabilities declared by the underlying networks of |nai|. */ + private void mixInUnderlyingCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) { + Network[] underlyingNetworks = nai.declaredUnderlyingNetworks; + Network defaultNetwork = getNetwork(getDefaultNetwork()); + if (underlyingNetworks == null && defaultNetwork != null) { + // null underlying networks means to track the default. + underlyingNetworks = new Network[] { defaultNetwork }; + } + + // TODO(b/124469351): Get capabilities directly from ConnectivityService instead. + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + Vpn.applyUnderlyingCapabilities(cm, underlyingNetworks, nc, nai.declaredMetered); + } + + /** * Augments the NetworkCapabilities passed in by a NetworkAgent with capabilities that are * maintained here that the NetworkAgent is not aware of (e.g., validated, captive portal, * and foreground status). @@ -6367,6 +6421,10 @@ public class ConnectivityService extends IConnectivityManager.Stub newNc.addCapability(NET_CAPABILITY_NOT_ROAMING); } + if (nai.supportsUnderlyingNetworks()) { + mixInUnderlyingCapabilities(nai, newNc); + } + return newNc; } @@ -6446,7 +6504,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!newNc.hasTransport(TRANSPORT_VPN)) { // Tell VPNs about updated capabilities, since they may need to // bubble those changes through. - updateAllVpnsCapabilities(); + propagateUnderlyingNetworkCapabilities(); } if (!newNc.equalsTransportTypes(prevNc)) { @@ -6766,7 +6824,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ? newNetwork.linkProperties.getTcpBufferSizes() : null); notifyIfacesChangedForNetworkStats(); // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks. - updateAllVpnsCapabilities(); + propagateUnderlyingNetworkCapabilities(); } private void processListenRequests(@NonNull final NetworkAgentInfo nai) { @@ -7228,7 +7286,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as // the VPN would switch from its default, blank capabilities to those // that reflect the capabilities of its underlying networks. - updateAllVpnsCapabilities(); + propagateUnderlyingNetworkCapabilities(); } networkAgent.created = true; } @@ -7270,8 +7328,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // doing. updateSignalStrengthThresholds(networkAgent, "CONNECT", null); - if (networkAgent.isVPN()) { - updateAllVpnsCapabilities(); + if (networkAgent.supportsUnderlyingNetworks()) { + propagateUnderlyingNetworkCapabilities(); } // Consider network even though it is not yet validated. @@ -7528,13 +7586,6 @@ public class ConnectivityService extends IConnectivityManager.Stub throwIfLockdownEnabled(); success = mVpns.get(user).setUnderlyingNetworks(networks); } - if (success) { - mHandler.post(() -> { - // Update VPN's capabilities based on updated underlying network set. - updateAllVpnsCapabilities(); - notifyIfacesChangedForNetworkStats(); - }); - } return success; } @@ -8210,13 +8261,12 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } - final Network[] underlyingNetworks; - synchronized (mVpns) { - final Vpn vpn = getVpnIfOwner(callbackUid); - underlyingNetworks = (vpn == null) ? null : vpn.getUnderlyingNetworks(); - } - if (underlyingNetworks != null) { - if (Arrays.asList(underlyingNetworks).contains(nai.network)) return true; + for (NetworkAgentInfo virtual : mNetworkAgentInfos.values()) { + if (virtual.supportsUnderlyingNetworks() + && virtual.networkCapabilities.getOwnerUid() == callbackUid + && ArrayUtils.contains(virtual.declaredUnderlyingNetworks, nai.network)) { + return true; + } } // Administrator UIDs also contains the Owner UID diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index e67b9d8ccd91..8706cdf41df9 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -6,3 +6,6 @@ per-file VibratorManagerService.java, VibratorService.java, DisplayThread.java = # Zram writeback per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com, srnvs@google.com + +# Userspace reboot +per-file UserspaceRebootLogger.java = ioffe@google.com, tomcherry@google.com diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java index e8e1a16d116b..a1cf8162f0e9 100644 --- a/services/core/java/com/android/server/RescueParty.java +++ b/services/core/java/com/android/server/RescueParty.java @@ -16,6 +16,8 @@ package com.android.server; +import static android.provider.DeviceConfig.Properties; + import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; import android.annotation.NonNull; @@ -36,6 +38,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.Settings; +import android.text.TextUtils; import android.util.ArraySet; import android.util.ExceptionUtils; import android.util.Log; @@ -93,6 +96,12 @@ public class RescueParty { static final long DEFAULT_OBSERVING_DURATION_MS = TimeUnit.DAYS.toMillis(2); @VisibleForTesting static final int DEVICE_CONFIG_RESET_MODE = Settings.RESET_MODE_TRUSTED_DEFAULTS; + // The DeviceConfig namespace containing all RescueParty switches. + @VisibleForTesting + static final String NAMESPACE_CONFIGURATION = "configuration"; + @VisibleForTesting + static final String NAMESPACE_TO_PACKAGE_MAPPING_FLAG = + "namespace_to_package_mapping"; private static final String NAME = "rescue-party-observer"; @@ -103,8 +112,6 @@ public class RescueParty { "persist.device_config.configuration.disable_rescue_party"; private static final String PROP_DISABLE_FACTORY_RESET_FLAG = "persist.device_config.configuration.disable_rescue_party_factory_reset"; - // The DeviceConfig namespace containing all RescueParty switches. - private static final String NAMESPACE_CONFIGURATION = "configuration"; private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT | ApplicationInfo.FLAG_SYSTEM; @@ -170,6 +177,81 @@ public class RescueParty { })); } + + /** + * Called when {@code RollbackManager} performs Mainline module rollbacks, + * to avoid rolled back modules consuming flag values only expected to work + * on modules of newer versions. + */ + public static void resetDeviceConfigForPackages(List<String> packageNames) { + if (packageNames == null) { + return; + } + Set<String> namespacesToReset = new ArraySet<String>(); + Iterator<String> it = packageNames.iterator(); + RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstanceIfCreated(); + // Get runtime package to namespace mapping if created. + if (rescuePartyObserver != null) { + while (it.hasNext()) { + String packageName = it.next(); + Set<String> runtimeAffectedNamespaces = + rescuePartyObserver.getAffectedNamespaceSet(packageName); + if (runtimeAffectedNamespaces != null) { + namespacesToReset.addAll(runtimeAffectedNamespaces); + } + } + } + // Get preset package to namespace mapping if created. + Set<String> presetAffectedNamespaces = getPresetNamespacesForPackages( + packageNames); + if (presetAffectedNamespaces != null) { + namespacesToReset.addAll(presetAffectedNamespaces); + } + + // Clear flags under the namespaces mapped to these packages. + // Using setProperties since DeviceConfig.resetToDefaults bans the current flag set. + Iterator<String> namespaceIt = namespacesToReset.iterator(); + while (namespaceIt.hasNext()) { + String namespaceToReset = namespaceIt.next(); + Properties properties = new Properties.Builder(namespaceToReset).build(); + try { + DeviceConfig.setProperties(properties); + } catch (DeviceConfig.BadConfigException exception) { + logCriticalInfo(Log.WARN, "namespace " + namespaceToReset + + " is already banned, skip reset."); + } + } + } + + private static Set<String> getPresetNamespacesForPackages(List<String> packageNames) { + Set<String> resultSet = new ArraySet<String>(); + try { + String flagVal = DeviceConfig.getString(NAMESPACE_CONFIGURATION, + NAMESPACE_TO_PACKAGE_MAPPING_FLAG, ""); + String[] mappingEntries = flagVal.split(","); + for (int i = 0; i < mappingEntries.length; i++) { + if (TextUtils.isEmpty(mappingEntries[i])) { + continue; + } + String[] splittedEntry = mappingEntries[i].split(":"); + if (splittedEntry.length != 2) { + throw new RuntimeException("Invalid mapping entry: " + mappingEntries[i]); + } + String namespace = splittedEntry[0]; + String packageName = splittedEntry[1]; + + if (packageNames.contains(packageName)) { + resultSet.add(namespace); + } + } + } catch (Exception e) { + resultSet.clear(); + Slog.e(TAG, "Failed to read preset package to namespaces mapping.", e); + } finally { + return resultSet; + } + } + @VisibleForTesting static long getElapsedRealtime() { return SystemClock.elapsedRealtime(); @@ -469,6 +551,14 @@ public class RescueParty { } } + /** Gets singleton instance. It returns null if the instance is not created yet.*/ + @Nullable + public static RescuePartyObserver getInstanceIfCreated() { + synchronized (RescuePartyObserver.class) { + return sRescuePartyObserver; + } + } + @VisibleForTesting static void reset() { synchronized (RescuePartyObserver.class) { diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 8033ce787b5f..04a52e049474 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -3213,6 +3213,9 @@ class StorageManagerService extends IStorageManager.Stub try { mVold.unlockUserKey(userId, serialNumber, encodeBytes(token), encodeBytes(secret)); + } catch (ServiceSpecificException sse) { + Slog.d(TAG, "Expected if the user has not unlocked the device.", sse); + return; } catch (Exception e) { Slog.wtf(TAG, e); return; diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING index ebeec39d6ae6..95af84293377 100644 --- a/services/core/java/com/android/server/TEST_MAPPING +++ b/services/core/java/com/android/server/TEST_MAPPING @@ -29,6 +29,10 @@ { "name": "CtsScopedStorageHostTest", "file_patterns": ["StorageManagerService\\.java"] + }, + { + "name": "CtsScopedStorageDeviceOnlyTest", + "file_patterns": ["StorageManagerService\\.java"] } ] } diff --git a/services/core/java/com/android/server/UserspaceRebootLogger.java b/services/core/java/com/android/server/UserspaceRebootLogger.java index 2403b637581f..89327b50883c 100644 --- a/services/core/java/com/android/server/UserspaceRebootLogger.java +++ b/services/core/java/com/android/server/UserspaceRebootLogger.java @@ -59,7 +59,7 @@ public final class UserspaceRebootLogger { */ public static void noteUserspaceRebootWasRequested() { if (!PowerManager.isRebootingUserspaceSupportedImpl()) { - Slog.wtf(TAG, "Userspace reboot is not supported."); + Slog.wtf(TAG, "noteUserspaceRebootWasRequested: Userspace reboot is not supported."); return; } @@ -77,7 +77,7 @@ public final class UserspaceRebootLogger { */ public static void noteUserspaceRebootSuccess() { if (!PowerManager.isRebootingUserspaceSupportedImpl()) { - Slog.wtf(TAG, "Userspace reboot is not supported."); + Slog.wtf(TAG, "noteUserspaceRebootSuccess: Userspace reboot is not supported."); return; } @@ -88,11 +88,11 @@ public final class UserspaceRebootLogger { /** * Returns {@code true} if {@code UserspaceRebootReported} atom should be logged. * - * <p>This call should only be made on devices supporting userspace reboot. + * <p>On devices that do not support userspace reboot this method will always return {@code + * false}. */ public static boolean shouldLogUserspaceRebootEvent() { if (!PowerManager.isRebootingUserspaceSupportedImpl()) { - Slog.wtf(TAG, "Userspace reboot is not supported."); return false; } @@ -110,7 +110,7 @@ public final class UserspaceRebootLogger { */ public static void logEventAsync(boolean userUnlocked, Executor executor) { if (!PowerManager.isRebootingUserspaceSupportedImpl()) { - Slog.wtf(TAG, "Userspace reboot is not supported."); + Slog.wtf(TAG, "logEventAsync: Userspace reboot is not supported."); return; } diff --git a/services/core/java/com/android/server/VibratorManagerService.java b/services/core/java/com/android/server/VibratorManagerService.java index 356cd0cd937b..f1f2815be8fa 100644 --- a/services/core/java/com/android/server/VibratorManagerService.java +++ b/services/core/java/com/android/server/VibratorManagerService.java @@ -159,7 +159,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { pw.println(" Prints this help text."); pw.println(""); pw.println(" list"); - pw.println(" Prints the id of device vibrators. This do not include any "); + pw.println(" Prints the id of device vibrators. This does not include any "); pw.println(" connected input device."); pw.println(""); } diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index e662553af731..db2b4e4edd2b 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -16,8 +16,6 @@ package com.android.server; -import static android.os.VibrationEffect.Composition.PrimitiveEffect; - import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppOpsManager; @@ -28,8 +26,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; -import android.content.res.Resources; -import android.hardware.input.InputManager; import android.hardware.vibrator.IVibrator; import android.os.BatteryStats; import android.os.Binder; @@ -45,7 +41,6 @@ import android.os.PowerManager.ServiceType; import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.Process; -import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; @@ -60,38 +55,33 @@ import android.os.WorkSource; import android.util.Slog; import android.util.SparseArray; import android.util.proto.ProtoOutputStream; -import android.view.InputDevice; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; +import com.android.server.vibrator.InputDeviceDelegate; +import com.android.server.vibrator.Vibration; import com.android.server.vibrator.VibrationScaler; import com.android.server.vibrator.VibrationSettings; - -import libcore.util.NativeAllocationRegistry; +import com.android.server.vibrator.VibratorController; +import com.android.server.vibrator.VibratorController.OnVibrationCompleteListener; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.text.SimpleDateFormat; +import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -public class VibratorService extends IVibratorService.Stub - implements InputManager.InputDeviceListener { +/** System implementation of {@link IVibratorService}. */ +public class VibratorService extends IVibratorService.Stub { private static final String TAG = "VibratorService"; - private static final SimpleDateFormat DEBUG_DATE_FORMAT = - new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); private static final boolean DEBUG = false; private static final String EXTERNAL_VIBRATOR_SERVICE = "external_vibrator_service"; - private static final long[] DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS = { 0, 30, 100, 30 }; - // Default vibration attributes. Used when vibration is requested without attributes private static final VibrationAttributes DEFAULT_ATTRIBUTES = new VibrationAttributes.Builder().build(); @@ -99,22 +89,17 @@ public class VibratorService extends IVibratorService.Stub // Used to generate globally unique vibration ids. private final AtomicInteger mNextVibrationId = new AtomicInteger(1); // 0 = no callback - private final LinkedList<VibrationInfo> mPreviousRingVibrations; - private final LinkedList<VibrationInfo> mPreviousNotificationVibrations; - private final LinkedList<VibrationInfo> mPreviousAlarmVibrations; - private final LinkedList<VibrationInfo> mPreviousExternalVibrations; - private final LinkedList<VibrationInfo> mPreviousVibrations; + private final LinkedList<Vibration.DebugInfo> mPreviousRingVibrations; + private final LinkedList<Vibration.DebugInfo> mPreviousNotificationVibrations; + private final LinkedList<Vibration.DebugInfo> mPreviousAlarmVibrations; + private final LinkedList<Vibration.DebugInfo> mPreviousExternalVibrations; + private final LinkedList<Vibration.DebugInfo> mPreviousVibrations; private final int mPreviousVibrationsLimit; - private final boolean mAllowPriorityVibrationsInLowPowerMode; - private final List<Integer> mSupportedEffects; - private final List<Integer> mSupportedPrimitives; - private final long mCapabilities; - private final int mDefaultVibrationAmplitude; - private final SparseArray<VibrationEffect> mFallbackEffects; private final SparseArray<Integer> mProcStatesCache = new SparseArray<>(); private final WorkSource mTmpWorkSource = new WorkSource(); private final Handler mH; private final Object mLock = new Object(); + private final VibratorController mVibratorController; private final Context mContext; private final PowerManager.WakeLock mWakeLock; @@ -122,61 +107,21 @@ public class VibratorService extends IVibratorService.Stub private final IBatteryStats mBatteryStatsService; private final String mSystemUiPackage; private PowerManagerInternal mPowerManagerInternal; - private InputManager mIm; private VibrationSettings mVibrationSettings; private VibrationScaler mVibrationScaler; + private InputDeviceDelegate mInputDeviceDelegate; - private final NativeWrapper mNativeWrapper; private volatile VibrateWaveformThread mThread; - // mInputDeviceVibrators lock should be acquired after mLock, if both are - // to be acquired - private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<>(); - private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators - private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators - @GuardedBy("mLock") private Vibration mCurrentVibration; + @GuardedBy("mLock") + private VibrationDeathRecipient mCurrentVibrationDeathRecipient; private int mCurVibUid = -1; private ExternalVibrationHolder mCurrentExternalVibration; - private boolean mVibratorUnderExternalControl; private boolean mLowPowerMode; - @GuardedBy("mLock") - private boolean mIsVibrating; - @GuardedBy("mLock") - private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners = - new RemoteCallbackList<>(); private SparseArray<Vibration> mAlwaysOnEffects = new SparseArray<>(); - static native long vibratorInit(OnCompleteListener listener); - - static native long vibratorGetFinalizer(); - - static native boolean vibratorExists(long nativeServicePtr); - - static native void vibratorOn(long nativeServicePtr, long milliseconds, long vibrationId); - - static native void vibratorOff(long nativeServicePtr); - - static native void vibratorSetAmplitude(long nativeServicePtr, int amplitude); - - static native int[] vibratorGetSupportedEffects(long nativeServicePtr); - - static native int[] vibratorGetSupportedPrimitives(long nativeServicePtr); - - static native long vibratorPerformEffect( - long nativeServicePtr, long effect, long strength, long vibrationId); - - static native void vibratorPerformComposedEffect(long nativeServicePtr, - VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId); - - static native void vibratorSetExternalControl(long nativeServicePtr, boolean enabled); - - static native long vibratorGetCapabilities(long nativeServicePtr); - static native void vibratorAlwaysOnEnable(long nativeServicePtr, long id, long effect, - long strength); - static native void vibratorAlwaysOnDisable(long nativeServicePtr, long id); - private final IUidObserver mUidObserver = new IUidObserver.Stub() { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { @@ -187,118 +132,65 @@ public class VibratorService extends IVibratorService.Stub mProcStatesCache.delete(uid); } - @Override public void onUidActive(int uid) { + @Override + public void onUidActive(int uid) { } - @Override public void onUidIdle(int uid, boolean disabled) { + @Override + public void onUidIdle(int uid, boolean disabled) { } - @Override public void onUidCachedChanged(int uid, boolean cached) { + @Override + public void onUidCachedChanged(int uid, boolean cached) { } }; - /** Listener for vibration completion callbacks from native. */ - public interface OnCompleteListener { + /** + * Implementation of {@link OnVibrationCompleteListener} with a weak reference to this service. + */ + private static final class VibrationCompleteListener implements OnVibrationCompleteListener { + private WeakReference<VibratorService> mServiceRef; + + VibrationCompleteListener(VibratorService service) { + mServiceRef = new WeakReference<>(service); + } - /** Callback triggered when vibration is complete, identified by {@link Vibration#id}. */ - void onComplete(long vibrationId); + @Override + public void onComplete(int vibratorId, long vibrationId) { + VibratorService service = mServiceRef.get(); + if (service != null) { + service.onVibrationComplete(vibrationId); + } + } } - /** Holder for a {@link VibrationEffect}. */ - private final class Vibration implements IBinder.DeathRecipient { - - public final IBinder token; - // Start time in CLOCK_BOOTTIME base. - public final long startTime; - public final VibrationAttributes attrs; - public final long id; - public final int uid; - public final String opPkg; - public final String reason; - - // The actual effect to be played. - public VibrationEffect effect; - // The original effect that was requested. Typically these two things differ because - // the effect was scaled based on the users vibration intensity settings. - public VibrationEffect originalEffect; - // The scale applied to the original effect. - public float scale; - - // Start/end times in unix epoch time. Only to be used for debugging purposes and to - // correlate with other system events, any duration calculations should be done use - // startTime so as not to be affected by discontinuities created by RTC adjustments. - private final long mStartTimeDebug; - private long mEndTimeDebug; - private VibrationInfo.Status mStatus; - - private Vibration(IBinder token, VibrationEffect effect, - VibrationAttributes attrs, int uid, String opPkg, String reason) { - this.token = token; - this.effect = effect; - this.id = mNextVibrationId.getAndIncrement(); - this.startTime = SystemClock.elapsedRealtime(); - this.attrs = attrs; - this.uid = uid; - this.opPkg = opPkg; - this.reason = reason; - mStartTimeDebug = System.currentTimeMillis(); - mStatus = VibrationInfo.Status.RUNNING; + /** Death recipient to bind {@link Vibration}. */ + private final class VibrationDeathRecipient implements IBinder.DeathRecipient { + + private final Vibration mVibration; + + private VibrationDeathRecipient(Vibration vibration) { + mVibration = vibration; } @Override public void binderDied() { synchronized (mLock) { - if (this == mCurrentVibration) { + if (mVibration == mCurrentVibration) { if (DEBUG) { Slog.d(TAG, "Vibration finished because binder died, cleaning up"); } - doCancelVibrateLocked(VibrationInfo.Status.CANCELLED); + doCancelVibrateLocked(Vibration.Status.CANCELLED); } } } - public void end(VibrationInfo.Status status) { - if (hasEnded()) { - // Vibration already ended, keep first ending status set and ignore this one. - return; - } - mStatus = status; - mEndTimeDebug = System.currentTimeMillis(); - } - - public boolean hasEnded() { - return mStatus != VibrationInfo.Status.RUNNING; - } - - public boolean hasTimeoutLongerThan(long millis) { - final long duration = effect.getDuration(); - return duration >= 0 && duration > millis; - } - - public boolean isHapticFeedback() { - return VibratorService.this.isHapticFeedback(attrs.getUsage()); - } - - public boolean isNotification() { - return VibratorService.this.isNotification(attrs.getUsage()); + private void linkToDeath() throws RemoteException { + mVibration.token.linkToDeath(this, 0); } - public boolean isRingtone() { - return VibratorService.this.isRingtone(attrs.getUsage()); - } - - public boolean isAlarm() { - return VibratorService.this.isAlarm(attrs.getUsage()); - } - - public boolean isFromSystem() { - return uid == Process.SYSTEM_UID || uid == 0 || mSystemUiPackage.equals(opPkg); - } - - public VibrationInfo toInfo() { - return new VibrationInfo( - mStartTimeDebug, mEndTimeDebug, effect, originalEffect, scale, attrs, - uid, opPkg, reason, mStatus); + private void unlinkToDeath() { + mVibration.token.unlinkToDeath(this, 0); } } @@ -310,17 +202,17 @@ public class VibratorService extends IVibratorService.Stub private final long mStartTimeDebug; private long mEndTimeDebug; - private VibrationInfo.Status mStatus; + private Vibration.Status mStatus; private ExternalVibrationHolder(ExternalVibration externalVibration) { this.externalVibration = externalVibration; this.scale = IExternalVibratorService.SCALE_NONE; mStartTimeDebug = System.currentTimeMillis(); - mStatus = VibrationInfo.Status.RUNNING; + mStatus = Vibration.Status.RUNNING; } - public void end(VibrationInfo.Status status) { - if (mStatus != VibrationInfo.Status.RUNNING) { + public void end(Vibration.Status status) { + if (mStatus != Vibration.Status.RUNNING) { // Vibration already ended, keep first ending status set and ignore this one. return; } @@ -328,8 +220,8 @@ public class VibratorService extends IVibratorService.Stub mEndTimeDebug = System.currentTimeMillis(); } - public VibrationInfo toInfo() { - return new VibrationInfo( + public Vibration.DebugInfo getDebugInfo() { + return new Vibration.DebugInfo( mStartTimeDebug, mEndTimeDebug, /* effect= */ null, /* originalEffect= */ null, scale, externalVibration.getVibrationAttributes(), externalVibration.getUid(), externalVibration.getPackage(), @@ -337,176 +229,19 @@ public class VibratorService extends IVibratorService.Stub } } - /** Debug information about vibrations. */ - private static class VibrationInfo { - - public enum Status { - RUNNING, - FINISHED, - CANCELLED, - ERROR_APP_OPS, - IGNORED, - IGNORED_APP_OPS, - IGNORED_BACKGROUND, - IGNORED_RINGTONE, - IGNORED_UNKNOWN_VIBRATION, - IGNORED_UNSUPPORTED, - IGNORED_FOR_ALARM, - IGNORED_FOR_EXTERNAL, - IGNORED_FOR_ONGOING, - IGNORED_FOR_POWER, - IGNORED_FOR_SETTINGS, - } - - private final long mStartTimeDebug; - private final long mEndTimeDebug; - private final VibrationEffect mEffect; - private final VibrationEffect mOriginalEffect; - private final float mScale; - private final VibrationAttributes mAttrs; - private final int mUid; - private final String mOpPkg; - private final String mReason; - private final VibrationInfo.Status mStatus; - - VibrationInfo(long startTimeDebug, long endTimeDebug, VibrationEffect effect, - VibrationEffect originalEffect, float scale, VibrationAttributes attrs, - int uid, String opPkg, String reason, VibrationInfo.Status status) { - mStartTimeDebug = startTimeDebug; - mEndTimeDebug = endTimeDebug; - mEffect = effect; - mOriginalEffect = originalEffect; - mScale = scale; - mAttrs = attrs; - mUid = uid; - mOpPkg = opPkg; - mReason = reason; - mStatus = status; - } - - @Override - public String toString() { - return new StringBuilder() - .append("startTime: ") - .append(DEBUG_DATE_FORMAT.format(new Date(mStartTimeDebug))) - .append(", endTime: ") - .append(mEndTimeDebug == 0 ? null - : DEBUG_DATE_FORMAT.format(new Date(mEndTimeDebug))) - .append(", status: ") - .append(mStatus.name().toLowerCase()) - .append(", effect: ") - .append(mEffect) - .append(", originalEffect: ") - .append(mOriginalEffect) - .append(", scale: ") - .append(String.format("%.2f", mScale)) - .append(", attrs: ") - .append(mAttrs) - .append(", uid: ") - .append(mUid) - .append(", opPkg: ") - .append(mOpPkg) - .append(", reason: ") - .append(mReason) - .toString(); - } - - void dumpProto(ProtoOutputStream proto, long fieldId) { - final long token = proto.start(fieldId); - proto.write(VibrationProto.START_TIME, mStartTimeDebug); - proto.write(VibrationProto.END_TIME, mEndTimeDebug); - proto.write(VibrationProto.STATUS, mStatus.ordinal()); - - final long attrsToken = proto.start(VibrationProto.ATTRIBUTES); - proto.write(VibrationAttributesProto.USAGE, mAttrs.getUsage()); - proto.write(VibrationAttributesProto.AUDIO_USAGE, mAttrs.getAudioUsage()); - proto.write(VibrationAttributesProto.FLAGS, mAttrs.getFlags()); - proto.end(attrsToken); - - if (mEffect != null) { - dumpEffect(proto, VibrationProto.EFFECT, mEffect); - } - if (mOriginalEffect != null) { - dumpEffect(proto, VibrationProto.ORIGINAL_EFFECT, mOriginalEffect); - } - - proto.end(token); - } - - private void dumpEffect(ProtoOutputStream proto, long fieldId, VibrationEffect effect) { - final long token = proto.start(fieldId); - if (effect instanceof VibrationEffect.OneShot) { - dumpEffect(proto, VibrationEffectProto.ONESHOT, (VibrationEffect.OneShot) effect); - } else if (effect instanceof VibrationEffect.Waveform) { - dumpEffect(proto, VibrationEffectProto.WAVEFORM, (VibrationEffect.Waveform) effect); - } else if (effect instanceof VibrationEffect.Prebaked) { - dumpEffect(proto, VibrationEffectProto.PREBAKED, (VibrationEffect.Prebaked) effect); - } else if (effect instanceof VibrationEffect.Composed) { - dumpEffect(proto, VibrationEffectProto.COMPOSED, (VibrationEffect.Composed) effect); - } - proto.end(token); - } - - private void dumpEffect(ProtoOutputStream proto, long fieldId, - VibrationEffect.OneShot effect) { - final long token = proto.start(fieldId); - proto.write(OneShotProto.DURATION, (int) effect.getDuration()); - proto.write(OneShotProto.AMPLITUDE, effect.getAmplitude()); - proto.end(token); - } - - private void dumpEffect(ProtoOutputStream proto, long fieldId, - VibrationEffect.Waveform effect) { - final long token = proto.start(fieldId); - for (long timing : effect.getTimings()) { - proto.write(WaveformProto.TIMINGS, (int) timing); - } - for (int amplitude : effect.getAmplitudes()) { - proto.write(WaveformProto.AMPLITUDES, amplitude); - } - proto.write(WaveformProto.REPEAT, effect.getRepeatIndex() >= 0); - proto.end(token); - } - - private void dumpEffect(ProtoOutputStream proto, long fieldId, - VibrationEffect.Prebaked effect) { - final long token = proto.start(fieldId); - proto.write(PrebakedProto.EFFECT_ID, effect.getId()); - proto.write(PrebakedProto.EFFECT_STRENGTH, effect.getEffectStrength()); - proto.write(PrebakedProto.FALLBACK, effect.shouldFallback()); - proto.end(token); - } - - private void dumpEffect(ProtoOutputStream proto, long fieldId, - VibrationEffect.Composed effect) { - final long token = proto.start(fieldId); - for (PrimitiveEffect primitive : effect.getPrimitiveEffects()) { - proto.write(ComposedProto.EFFECT_IDS, primitive.id); - proto.write(ComposedProto.EFFECT_SCALES, primitive.scale); - proto.write(ComposedProto.DELAYS, primitive.delay); - } - proto.end(token); - } - } - VibratorService(Context context) { this(context, new Injector()); } @VisibleForTesting VibratorService(Context context, Injector injector) { - mNativeWrapper = injector.getNativeWrapper(); mH = injector.createHandler(Looper.myLooper()); - - mNativeWrapper.vibratorInit(this::onVibrationComplete); + mVibratorController = injector.createVibratorController( + new VibrationCompleteListener(this)); // Reset the hardware to a default state, in case this is a runtime // restart instead of a fresh boot. - mNativeWrapper.vibratorOff(); - - mSupportedEffects = asList(mNativeWrapper.vibratorGetSupportedEffects()); - mSupportedPrimitives = asList(mNativeWrapper.vibratorGetSupportedPrimitives()); - mCapabilities = mNativeWrapper.vibratorGetCapabilities(); + mVibratorController.off(); mContext = context; PowerManager pm = context.getSystemService(PowerManager.class); @@ -522,12 +257,6 @@ public class VibratorService extends IVibratorService.Stub mPreviousVibrationsLimit = mContext.getResources().getInteger( com.android.internal.R.integer.config_previousVibrationsDumpLimit); - mDefaultVibrationAmplitude = mContext.getResources().getInteger( - com.android.internal.R.integer.config_defaultVibrationAmplitude); - - mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode); - mPreviousRingVibrations = new LinkedList<>(); mPreviousNotificationVibrations = new LinkedList<>(); mPreviousAlarmVibrations = new LinkedList<>(); @@ -538,48 +267,15 @@ public class VibratorService extends IVibratorService.Stub filter.addAction(Intent.ACTION_SCREEN_OFF); context.registerReceiver(mIntentReceiver, filter); - VibrationEffect clickEffect = createEffectFromResource( - com.android.internal.R.array.config_virtualKeyVibePattern); - VibrationEffect doubleClickEffect = VibrationEffect.createWaveform( - DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS, -1 /*repeatIndex*/); - VibrationEffect heavyClickEffect = createEffectFromResource( - com.android.internal.R.array.config_longPressVibePattern); - VibrationEffect tickEffect = createEffectFromResource( - com.android.internal.R.array.config_clockTickVibePattern); - - mFallbackEffects = new SparseArray<>(); - mFallbackEffects.put(VibrationEffect.EFFECT_CLICK, clickEffect); - mFallbackEffects.put(VibrationEffect.EFFECT_DOUBLE_CLICK, doubleClickEffect); - mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect); - mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, heavyClickEffect); - - mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK, - VibrationEffect.get(VibrationEffect.EFFECT_TICK, false)); - injector.addService(EXTERNAL_VIBRATOR_SERVICE, new ExternalVibratorService()); } - private VibrationEffect createEffectFromResource(int resId) { - long[] timings = getLongIntArray(mContext.getResources(), resId); - return createEffectFromTimings(timings); - } - - private static VibrationEffect createEffectFromTimings(long[] timings) { - if (timings == null || timings.length == 0) { - return null; - } else if (timings.length == 1) { - return VibrationEffect.createOneShot(timings[0], VibrationEffect.DEFAULT_AMPLITUDE); - } else { - return VibrationEffect.createWaveform(timings, -1); - } - } - public void systemReady() { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorService#systemReady"); try { - mIm = mContext.getSystemService(InputManager.class); mVibrationSettings = new VibrationSettings(mContext, mH); mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings); + mInputDeviceDelegate = new InputDeviceDelegate(mContext, mH); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mPowerManagerInternal.registerLowPowerModeObserver( @@ -626,14 +322,19 @@ public class VibratorService extends IVibratorService.Stub if (DEBUG) { Slog.d(TAG, "Vibration finished by callback, cleaning up"); } - doCancelVibrateLocked(VibrationInfo.Status.FINISHED); + doCancelVibrateLocked(Vibration.Status.FINISHED); } } } @Override // Binder call public boolean hasVibrator() { - return doVibratorExists(); + // For now, we choose to ignore the presence of input devices that have vibrators + // when reporting whether the device has a vibrator. Applications often use this + // information to decide whether to enable certain features so they expect the + // result of hasVibrator() to be constant. For now, just report whether + // the device has a built-in vibrator. + return mVibratorController.isAvailable(); } @Override // Binder call @@ -641,32 +342,7 @@ public class VibratorService extends IVibratorService.Stub if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) { throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission"); } - synchronized (mLock) { - return mIsVibrating; - } - } - - @GuardedBy("mLock") - private void notifyStateListenerLocked(IVibratorStateListener listener) { - try { - listener.onVibrating(mIsVibrating); - } catch (RemoteException | RuntimeException e) { - Slog.e(TAG, "Vibrator callback failed to call", e); - } - } - - @GuardedBy("mLock") - private void notifyStateListenersLocked() { - final int length = mVibratorStateListeners.beginBroadcast(); - try { - for (int i = 0; i < length; i++) { - final IVibratorStateListener listener = - mVibratorStateListeners.getBroadcastItem(i); - notifyStateListenerLocked(listener); - } - } finally { - mVibratorStateListeners.finishBroadcast(); - } + return mVibratorController.isVibrating(); } @Override // Binder call @@ -674,19 +350,7 @@ public class VibratorService extends IVibratorService.Stub if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) { throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission"); } - synchronized (mLock) { - final long token = Binder.clearCallingIdentity(); - try { - if (!mVibratorStateListeners.register(listener)) { - return false; - } - // Notify its callback after new client registered. - notifyStateListenerLocked(listener); - return true; - } finally { - Binder.restoreCallingIdentity(token); - } - } + return mVibratorController.registerVibratorStateListener(listener); } @Override // Binder call @@ -695,54 +359,26 @@ public class VibratorService extends IVibratorService.Stub if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) { throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission"); } - synchronized (mLock) { - final long token = Binder.clearCallingIdentity(); - try { - return mVibratorStateListeners.unregister(listener); - } finally { - Binder.restoreCallingIdentity(token); - } - } + return mVibratorController.unregisterVibratorStateListener(listener); } @Override // Binder call public boolean hasAmplitudeControl() { - synchronized (mInputDeviceVibrators) { - // Input device vibrators don't support amplitude controls yet, but are still used over - // the system vibrator when connected. - return hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL) - && mInputDeviceVibrators.isEmpty(); - } + // Input device vibrators always support amplitude controls. + return mInputDeviceDelegate.isAvailable() + || mVibratorController.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL); } @Override // Binder call public int[] areEffectsSupported(int[] effectIds) { - int[] supported = new int[effectIds.length]; - if (mSupportedEffects == null) { - Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN); - } else { - for (int i = 0; i < effectIds.length; i++) { - supported[i] = mSupportedEffects.contains(effectIds[i]) - ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES - : Vibrator.VIBRATION_EFFECT_SUPPORT_NO; - } - } - return supported; + return mVibratorController.areEffectsSupported(effectIds); } @Override // Binder call public boolean[] arePrimitivesSupported(int[] primitiveIds) { - boolean[] supported = new boolean[primitiveIds.length]; - if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS) || mSupportedPrimitives == null) { - return supported; - } - for (int i = 0; i < primitiveIds.length; i++) { - supported[i] = mSupportedPrimitives.contains(primitiveIds[i]); - } - return supported; + return mVibratorController.arePrimitivesSupported(primitiveIds); } - private static List<Integer> asList(int... vals) { if (vals == null) { return null; @@ -760,14 +396,14 @@ public class VibratorService extends IVibratorService.Stub if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) { throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission"); } - if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + if (!mVibratorController.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { Slog.e(TAG, "Always-on effects not supported."); return false; } if (effect == null) { synchronized (mLock) { mAlwaysOnEffects.delete(alwaysOnId); - mNativeWrapper.vibratorAlwaysOnDisable(alwaysOnId); + mVibratorController.updateAlwaysOn(alwaysOnId, /* effect= */ null); } } else { if (!verifyVibrationEffect(effect)) { @@ -779,7 +415,8 @@ public class VibratorService extends IVibratorService.Stub } attrs = fixupVibrationAttributes(attrs); synchronized (mLock) { - Vibration vib = new Vibration(null, effect, attrs, uid, opPkg, null); + Vibration vib = new Vibration(null, mNextVibrationId.getAndIncrement(), effect, + attrs, uid, opPkg, null); mAlwaysOnEffects.put(alwaysOnId, vib); updateAlwaysOnLocked(alwaysOnId, vib); } @@ -839,18 +476,6 @@ public class VibratorService extends IVibratorService.Stub return attrs; } - private static long[] getLongIntArray(Resources r, int resid) { - int[] ar = r.getIntArray(resid); - if (ar == null) { - return null; - } - long[] out = new long[ar.length]; - for (int i = 0; i < ar.length; i++) { - out[i] = ar[i]; - } - return out; - } - @Override // Binder call public void vibrate(int uid, String opPkg, VibrationEffect effect, @Nullable VibrationAttributes attrs, String reason, IBinder token) { @@ -869,24 +494,26 @@ public class VibratorService extends IVibratorService.Stub } attrs = fixupVibrationAttributes(attrs); - Vibration vib = new Vibration(token, effect, attrs, uid, opPkg, reason); + Vibration vib = new Vibration(token, mNextVibrationId.getAndIncrement(), effect, attrs, + uid, opPkg, reason); // If our current vibration is longer than the new vibration and is the same amplitude, // then just let the current one finish. synchronized (mLock) { + VibrationEffect currentEffect = + mCurrentVibration == null ? null : mCurrentVibration.getEffect(); if (effect instanceof VibrationEffect.OneShot - && mCurrentVibration != null - && mCurrentVibration.effect instanceof VibrationEffect.OneShot) { + && currentEffect instanceof VibrationEffect.OneShot) { VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect; VibrationEffect.OneShot currentOneShot = - (VibrationEffect.OneShot) mCurrentVibration.effect; - if (mCurrentVibration.hasTimeoutLongerThan(newOneShot.getDuration()) + (VibrationEffect.OneShot) currentEffect; + if (currentOneShot.getDuration() > newOneShot.getDuration() && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) { if (DEBUG) { Slog.d(TAG, "Ignoring incoming vibration in favor of current vibration"); } - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_FOR_ONGOING); + endVibrationLocked(vib, Vibration.Status.IGNORED_FOR_ONGOING); return; } } @@ -898,7 +525,7 @@ public class VibratorService extends IVibratorService.Stub if (DEBUG) { Slog.d(TAG, "Ignoring incoming vibration for current external vibration"); } - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_FOR_EXTERNAL); + endVibrationLocked(vib, Vibration.Status.IGNORED_FOR_EXTERNAL); return; } @@ -908,32 +535,32 @@ public class VibratorService extends IVibratorService.Stub // alarms, in favor of one-shot vibrations that are likely quite short. if (!isRepeatingVibration(effect) && mCurrentVibration != null - && isRepeatingVibration(mCurrentVibration.effect)) { + && isRepeatingVibration(currentEffect)) { if (DEBUG) { Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration"); } - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_FOR_ALARM); + endVibrationLocked(vib, Vibration.Status.IGNORED_FOR_ALARM); return; } if (mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND - && !vib.isNotification() && !vib.isRingtone() && !vib.isAlarm()) { + && !isNotification(vib) && !isRingtone(vib) && !isAlarm(vib)) { Slog.e(TAG, "Ignoring incoming vibration as process with" + " uid= " + uid + " is background," + " attrs= " + vib.attrs); - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_BACKGROUND); + endVibrationLocked(vib, Vibration.Status.IGNORED_BACKGROUND); return; } - linkVibration(vib); + linkVibrationLocked(vib); final long ident = Binder.clearCallingIdentity(); try { - doCancelVibrateLocked(VibrationInfo.Status.CANCELLED); + doCancelVibrateLocked(Vibration.Status.CANCELLED); startVibrationLocked(vib); if (!vib.hasEnded() && mCurrentVibration.id != vib.id) { // Vibration was unexpectedly ignored: add to list for debugging - endVibrationLocked(vib, VibrationInfo.Status.IGNORED); + endVibrationLocked(vib, Vibration.Status.IGNORED); } } finally { Binder.restoreCallingIdentity(ident); @@ -953,13 +580,13 @@ public class VibratorService extends IVibratorService.Stub return effect.getDuration() == Long.MAX_VALUE; } - private void endVibrationLocked(Vibration vib, VibrationInfo.Status status) { - final LinkedList<VibrationInfo> previousVibrations; - if (vib.isRingtone()) { + private void endVibrationLocked(Vibration vib, Vibration.Status status) { + final LinkedList<Vibration.DebugInfo> previousVibrations; + if (isRingtone(vib)) { previousVibrations = mPreviousRingVibrations; - } else if (vib.isNotification()) { + } else if (isNotification(vib)) { previousVibrations = mPreviousNotificationVibrations; - } else if (vib.isAlarm()) { + } else if (isAlarm(vib)) { previousVibrations = mPreviousAlarmVibrations; } else { previousVibrations = mPreviousVibrations; @@ -969,15 +596,15 @@ public class VibratorService extends IVibratorService.Stub previousVibrations.removeFirst(); } vib.end(status); - previousVibrations.addLast(vib.toInfo()); + previousVibrations.addLast(vib.getDebugInfo()); } - private void endVibrationLocked(ExternalVibrationHolder vib, VibrationInfo.Status status) { + private void endVibrationLocked(ExternalVibrationHolder vib, Vibration.Status status) { if (mPreviousExternalVibrations.size() > mPreviousVibrationsLimit) { mPreviousExternalVibrations.removeFirst(); } vib.end(status); - mPreviousExternalVibrations.addLast(vib.toInfo()); + mPreviousExternalVibrations.addLast(vib.getDebugInfo()); } @Override // Binder call @@ -993,7 +620,7 @@ public class VibratorService extends IVibratorService.Stub } final long ident = Binder.clearCallingIdentity(); try { - doCancelVibrateLocked(VibrationInfo.Status.CANCELLED); + doCancelVibrateLocked(Vibration.Status.CANCELLED); } finally { Binder.restoreCallingIdentity(ident); } @@ -1002,7 +629,7 @@ public class VibratorService extends IVibratorService.Stub } @GuardedBy("mLock") - private void doCancelVibrateLocked(VibrationInfo.Status status) { + private void doCancelVibrateLocked(Vibration.Status status) { Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doCancelVibrateLocked"); try { @@ -1014,7 +641,7 @@ public class VibratorService extends IVibratorService.Stub endVibrationLocked(mCurrentExternalVibration, status); mCurrentExternalVibration.externalVibration.mute(); mCurrentExternalVibration = null; - setVibratorUnderExternalControl(false); + mVibratorController.setExternalControl(false); } doVibratorOff(); reportFinishVibrationLocked(status); @@ -1031,7 +658,7 @@ public class VibratorService extends IVibratorService.Stub synchronized (mLock) { // Make sure the vibration is really done. This also reports that the vibration is // finished. - doCancelVibrateLocked(VibrationInfo.Status.FINISHED); + doCancelVibrateLocked(Vibration.Status.FINISHED); } } @@ -1055,23 +682,22 @@ public class VibratorService extends IVibratorService.Stub try { // Set current vibration before starting it, so callback will work. mCurrentVibration = vib; - if (vib.effect instanceof VibrationEffect.OneShot) { + VibrationEffect effect = vib.getEffect(); + if (effect instanceof VibrationEffect.OneShot) { Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); doVibratorOn(vib); - } else if (vib.effect instanceof VibrationEffect.Waveform) { - // mThread better be null here. doCancelVibrate should always be - // called before startNextVibrationLocked or startVibrationLocked. - mThread = new VibrateWaveformThread(vib); - mThread.start(); - } else if (vib.effect instanceof VibrationEffect.Prebaked) { + } else if (effect instanceof VibrationEffect.Waveform) { + Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); + doVibratorWaveformEffectLocked(vib); + } else if (effect instanceof VibrationEffect.Prebaked) { Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); doVibratorPrebakedEffectLocked(vib); - } else if (vib.effect instanceof VibrationEffect.Composed) { + } else if (effect instanceof VibrationEffect.Composed) { Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); doVibratorComposedEffectLocked(vib); } else { Slog.e(TAG, "Unknown vibration type, ignoring"); - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_UNKNOWN_VIBRATION); + endVibrationLocked(vib, Vibration.Status.IGNORED_UNKNOWN_VIBRATION); // The set current vibration is not actually playing, so drop it. mCurrentVibration = null; } @@ -1093,11 +719,7 @@ public class VibratorService extends IVibratorService.Stub /** Scale the vibration effect by the intensity as appropriate based its intent. */ private void applyVibrationIntensityScalingLocked(Vibration vib) { - VibrationEffect scaled = mVibrationScaler.scale(vib.effect, vib.attrs.getUsage()); - if (!scaled.equals(vib.effect)) { - vib.originalEffect = vib.effect; - vib.effect = scaled; - } + vib.updateEffect(mVibrationScaler.scale(vib.getEffect(), vib.attrs.getUsage())); } private static boolean shouldBypassDnd(VibrationAttributes attrs) { @@ -1123,21 +745,21 @@ public class VibratorService extends IVibratorService.Stub private boolean shouldVibrate(Vibration vib) { if (!shouldVibrateForPowerModeLocked(vib)) { - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_FOR_POWER); + endVibrationLocked(vib, Vibration.Status.IGNORED_FOR_POWER); return false; } int intensity = mVibrationSettings.getCurrentIntensity(vib.attrs.getUsage()); if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) { - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_FOR_SETTINGS); + endVibrationLocked(vib, Vibration.Status.IGNORED_FOR_SETTINGS); return false; } - if (vib.isRingtone() && !mVibrationSettings.shouldVibrateForRingtone()) { + if (isRingtone(vib) && !mVibrationSettings.shouldVibrateForRingtone()) { if (DEBUG) { Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); } - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_RINGTONE); + endVibrationLocked(vib, Vibration.Status.IGNORED_RINGTONE); return false; } @@ -1147,9 +769,9 @@ public class VibratorService extends IVibratorService.Stub // We might be getting calls from within system_server, so we don't actually // want to throw a SecurityException here. Slog.w(TAG, "Would be an error: vibrate from uid " + vib.uid); - endVibrationLocked(vib, VibrationInfo.Status.ERROR_APP_OPS); + endVibrationLocked(vib, Vibration.Status.ERROR_APP_OPS); } else { - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_APP_OPS); + endVibrationLocked(vib, Vibration.Status.IGNORED_APP_OPS); } return false; } @@ -1158,14 +780,14 @@ public class VibratorService extends IVibratorService.Stub } @GuardedBy("mLock") - private void reportFinishVibrationLocked(VibrationInfo.Status status) { + private void reportFinishVibrationLocked(Vibration.Status status) { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "reportFinishVibrationLocked"); try { if (mCurrentVibration != null) { endVibrationLocked(mCurrentVibration, status); mAppOps.finishOp(AppOpsManager.OP_VIBRATE, mCurrentVibration.uid, mCurrentVibration.opPkg); - unlinkVibration(mCurrentVibration); + unlinkVibrationLocked(); mCurrentVibration = null; } } finally { @@ -1173,73 +795,45 @@ public class VibratorService extends IVibratorService.Stub } } - private void linkVibration(Vibration vib) { + @GuardedBy("mLock") + private void linkVibrationLocked(Vibration vib) { + // Unlink previously linked vibration, if any. + unlinkVibrationLocked(); // Only link against waveforms since they potentially don't have a finish if // they're repeating. Let other effects just play out until they're done. - if (vib.effect instanceof VibrationEffect.Waveform) { + if (vib.getEffect() instanceof VibrationEffect.Waveform) { try { - vib.token.linkToDeath(vib, 0); + mCurrentVibrationDeathRecipient = new VibrationDeathRecipient(vib); + mCurrentVibrationDeathRecipient.linkToDeath(); } catch (RemoteException e) { return; } } } - private void unlinkVibration(Vibration vib) { - if (vib.effect instanceof VibrationEffect.Waveform) { - vib.token.unlinkToDeath(vib, 0); + @GuardedBy("mLock") + private void unlinkVibrationLocked() { + if (mCurrentVibrationDeathRecipient != null) { + mCurrentVibrationDeathRecipient.unlinkToDeath(); + mCurrentVibrationDeathRecipient = null; } } private void updateVibrators() { synchronized (mLock) { - boolean devicesUpdated = updateInputDeviceVibratorsLocked(); + boolean devicesUpdated = mInputDeviceDelegate.updateInputDeviceVibrators( + mVibrationSettings.shouldVibrateInputDevices()); boolean lowPowerModeUpdated = updateLowPowerModeLocked(); if (devicesUpdated || lowPowerModeUpdated) { // If the state changes out from under us then just reset. - doCancelVibrateLocked(VibrationInfo.Status.CANCELLED); + doCancelVibrateLocked(Vibration.Status.CANCELLED); } updateAlwaysOnLocked(); } } - private boolean updateInputDeviceVibratorsLocked() { - boolean changed = false; - boolean vibrateInputDevices = mVibrationSettings.shouldVibrateInputDevices(); - if (vibrateInputDevices != mVibrateInputDevicesSetting) { - changed = true; - mVibrateInputDevicesSetting = vibrateInputDevices; - } - - if (mVibrateInputDevicesSetting) { - if (!mInputDeviceListenerRegistered) { - mInputDeviceListenerRegistered = true; - mIm.registerInputDeviceListener(this, mH); - } - } else { - if (mInputDeviceListenerRegistered) { - mInputDeviceListenerRegistered = false; - mIm.unregisterInputDeviceListener(this); - } - } - - mInputDeviceVibrators.clear(); - if (mVibrateInputDevicesSetting) { - int[] ids = mIm.getInputDeviceIds(); - for (int i = 0; i < ids.length; i++) { - InputDevice device = mIm.getInputDevice(ids[i]); - Vibrator vibrator = device.getVibrator(); - if (vibrator.hasVibrator()) { - mInputDeviceVibrators.add(vibrator); - } - } - return true; - } - return changed; - } - private boolean updateLowPowerModeLocked() { boolean lowPowerMode = mPowerManagerInternal .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled; @@ -1251,13 +845,13 @@ public class VibratorService extends IVibratorService.Stub } private void updateAlwaysOnLocked(int id, Vibration vib) { + VibrationEffect.Prebaked effect; if (!shouldVibrate(vib)) { - mNativeWrapper.vibratorAlwaysOnDisable(id); + effect = null; } else { - VibrationEffect.Prebaked scaled = mVibrationScaler.scale(vib.effect, - vib.attrs.getUsage()); - mNativeWrapper.vibratorAlwaysOnEnable(id, scaled.getId(), scaled.getEffectStrength()); + effect = mVibrationScaler.scale(vib.getEffect(), vib.attrs.getUsage()); } + mVibratorController.updateAlwaysOn(id, effect); } private void updateAlwaysOnLocked() { @@ -1268,85 +862,64 @@ public class VibratorService extends IVibratorService.Stub } } - @Override - public void onInputDeviceAdded(int deviceId) { - updateVibrators(); - } - - @Override - public void onInputDeviceChanged(int deviceId) { - updateVibrators(); - } - - @Override - public void onInputDeviceRemoved(int deviceId) { - updateVibrators(); - } - - private boolean doVibratorExists() { - // For now, we choose to ignore the presence of input devices that have vibrators - // when reporting whether the device has a vibrator. Applications often use this - // information to decide whether to enable certain features so they expect the - // result of hasVibrator() to be constant. For now, just report whether - // the device has a built-in vibrator. - //synchronized (mInputDeviceVibrators) { - // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); - //} - return mNativeWrapper.vibratorExists(); - } - private void doVibratorOn(Vibration vib) { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOn"); try { - synchronized (mInputDeviceVibrators) { - final VibrationEffect.OneShot oneShot = vib.effect.resolve( - mDefaultVibrationAmplitude); - if (DEBUG) { - Slog.d(TAG, "Turning vibrator on for " + oneShot.getDuration() + " ms" - + " with amplitude " + oneShot.getAmplitude() + "."); - } + final VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.getEffect(); + if (DEBUG) { + Slog.d(TAG, "Turning vibrator on for " + oneShot.getDuration() + " ms" + + " with amplitude " + oneShot.getAmplitude() + "."); + } + boolean inputDevicesAvailable = mInputDeviceDelegate.vibrateIfAvailable( + vib.uid, vib.opPkg, oneShot, vib.reason, vib.attrs); + if (inputDevicesAvailable) { + // The set current vibration is no longer being played by this service, so drop it. + mCurrentVibration = null; + endVibrationLocked(vib, Vibration.Status.FORWARDED_TO_INPUT_DEVICES); + } else { noteVibratorOnLocked(vib.uid, oneShot.getDuration()); - final int vibratorCount = mInputDeviceVibrators.size(); - if (vibratorCount != 0) { - for (int i = 0; i < vibratorCount; i++) { - mInputDeviceVibrators.get(i).vibrate(vib.uid, vib.opPkg, oneShot, - vib.reason, vib.attrs); - } - } else { - // Note: ordering is important here! Many haptic drivers will reset their - // amplitude when enabled, so we always have to enable first, then set the - // amplitude. - mNativeWrapper.vibratorOn(oneShot.getDuration(), vib.id); - doVibratorSetAmplitude(oneShot.getAmplitude()); - } + // Note: ordering is important here! Many haptic drivers will reset their + // amplitude when enabled, so we always have to enable first, then set the + // amplitude. + mVibratorController.on(oneShot.getDuration(), vib.id); + mVibratorController.setAmplitude(oneShot.getAmplitude()); } } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } } - private void doVibratorSetAmplitude(int amplitude) { - if (hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { - mNativeWrapper.vibratorSetAmplitude(amplitude); + private void doVibratorOff() { + Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOff"); + try { + if (DEBUG) { + Slog.d(TAG, "Turning vibrator off."); + } + noteVibratorOffLocked(); + boolean inputDevicesAvailable = mInputDeviceDelegate.cancelVibrateIfAvailable(); + if (!inputDevicesAvailable) { + mVibratorController.off(); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } } - private void doVibratorOff() { - Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOff"); + @GuardedBy("mLock") + private void doVibratorWaveformEffectLocked(Vibration vib) { + Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorWaveformEffectLocked"); try { - synchronized (mInputDeviceVibrators) { - if (DEBUG) { - Slog.d(TAG, "Turning vibrator off."); - } - noteVibratorOffLocked(); - final int vibratorCount = mInputDeviceVibrators.size(); - if (vibratorCount != 0) { - for (int i = 0; i < vibratorCount; i++) { - mInputDeviceVibrators.get(i).cancel(); - } - } else { - mNativeWrapper.vibratorOff(); - } + boolean inputDevicesAvailable = mInputDeviceDelegate.vibrateIfAvailable( + vib.uid, vib.opPkg, vib.getEffect(), vib.reason, vib.attrs); + if (inputDevicesAvailable) { + // The set current vibration is no longer being played by this service, so drop it. + mCurrentVibration = null; + endVibrationLocked(vib, Vibration.Status.FORWARDED_TO_INPUT_DEVICES); + } else { + // mThread better be null here. doCancelVibrate should always be + // called before startNextVibrationLocked or startVibrationLocked. + mThread = new VibrateWaveformThread(vib); + mThread.start(); } } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); @@ -1357,37 +930,33 @@ public class VibratorService extends IVibratorService.Stub private void doVibratorPrebakedEffectLocked(Vibration vib) { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorPrebakedEffectLocked"); try { - final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.effect; - final boolean usingInputDeviceVibrators; - synchronized (mInputDeviceVibrators) { - usingInputDeviceVibrators = !mInputDeviceVibrators.isEmpty(); - } - // Input devices don't support prebaked effect, so skip trying it with them. - if (!usingInputDeviceVibrators) { - long duration = mNativeWrapper.vibratorPerformEffect( - prebaked.getId(), prebaked.getEffectStrength(), vib.id); + final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.getEffect(); + // Input devices don't support prebaked effect, so skip trying it with them and allow + // fallback to be attempted. + if (!mInputDeviceDelegate.isAvailable()) { + long duration = mVibratorController.on(prebaked, vib.id); if (duration > 0) { noteVibratorOnLocked(vib.uid, duration); return; } } - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_UNSUPPORTED); + endVibrationLocked(vib, Vibration.Status.IGNORED_UNSUPPORTED); // The set current vibration is not actually playing, so drop it. mCurrentVibration = null; if (!prebaked.shouldFallback()) { return; } - VibrationEffect effect = getFallbackEffect(prebaked.getId()); + VibrationEffect effect = mVibrationSettings.getFallbackEffect(prebaked.getId()); if (effect == null) { Slog.w(TAG, "Failed to play prebaked effect, no fallback"); return; } - Vibration fallbackVib = new Vibration(vib.token, effect, vib.attrs, vib.uid, - vib.opPkg, vib.reason + " (fallback)"); + Vibration fallbackVib = new Vibration(vib.token, mNextVibrationId.getAndIncrement(), + effect, vib.attrs, vib.uid, vib.opPkg, vib.reason + " (fallback)"); // Set current vibration before starting it, so callback will work. mCurrentVibration = fallbackVib; - linkVibration(fallbackVib); + linkVibrationLocked(fallbackVib); applyVibrationIntensityScalingLocked(fallbackVib); startVibrationInnerLocked(fallbackVib); } finally { @@ -1400,53 +969,49 @@ public class VibratorService extends IVibratorService.Stub Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorComposedEffectLocked"); try { - final VibrationEffect.Composed composed = (VibrationEffect.Composed) vib.effect; - final boolean usingInputDeviceVibrators; - synchronized (mInputDeviceVibrators) { - usingInputDeviceVibrators = !mInputDeviceVibrators.isEmpty(); - } - // Input devices don't support composed effect, so skip trying it with them. - if (usingInputDeviceVibrators || !hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { - endVibrationLocked(vib, VibrationInfo.Status.IGNORED_UNSUPPORTED); + final VibrationEffect.Composed composed = (VibrationEffect.Composed) vib.getEffect(); + boolean inputDevicesAvailable = mInputDeviceDelegate.vibrateIfAvailable( + vib.uid, vib.opPkg, composed, vib.reason, vib.attrs); + if (inputDevicesAvailable) { + // The set current vibration is no longer being played by this service, so drop it. + mCurrentVibration = null; + endVibrationLocked(vib, Vibration.Status.FORWARDED_TO_INPUT_DEVICES); + return; + } else if (!mVibratorController.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { // The set current vibration is not actually playing, so drop it. mCurrentVibration = null; + endVibrationLocked(vib, Vibration.Status.IGNORED_UNSUPPORTED); return; } - PrimitiveEffect[] primitiveEffects = - composed.getPrimitiveEffects().toArray(new PrimitiveEffect[0]); - mNativeWrapper.vibratorPerformComposedEffect(primitiveEffects, vib.id); + mVibratorController.on(composed, vib.id); // Composed effects don't actually give us an estimated duration, so we just guess here. - noteVibratorOnLocked(vib.uid, 10 * primitiveEffects.length); + noteVibratorOnLocked(vib.uid, 10 * composed.getPrimitiveEffects().size()); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } } - private boolean hasCapability(long capability) { - return (mCapabilities & capability) == capability; - } - - private VibrationEffect getFallbackEffect(int effectId) { - return mFallbackEffects.get(effectId); + private static boolean isNotification(Vibration vib) { + return vib.attrs.getUsage() == VibrationAttributes.USAGE_NOTIFICATION; } - private static boolean isNotification(int usageHint) { - return usageHint == VibrationAttributes.USAGE_NOTIFICATION; + private static boolean isRingtone(Vibration vib) { + return vib.attrs.getUsage() == VibrationAttributes.USAGE_RINGTONE; } - private static boolean isRingtone(int usageHint) { - return usageHint == VibrationAttributes.USAGE_RINGTONE; + private static boolean isHapticFeedback(Vibration vib) { + return vib.attrs.getUsage() == VibrationAttributes.USAGE_TOUCH; } - private static boolean isHapticFeedback(int usageHint) { - return usageHint == VibrationAttributes.USAGE_TOUCH; + private static boolean isAlarm(Vibration vib) { + return vib.attrs.getUsage() == VibrationAttributes.USAGE_ALARM; } - private static boolean isAlarm(int usageHint) { - return usageHint == VibrationAttributes.USAGE_ALARM; + private boolean isFromSystem(Vibration vib) { + return vib.uid == Process.SYSTEM_UID || vib.uid == 0 || mSystemUiPackage.equals(vib.opPkg); } private void noteVibratorOnLocked(int uid, long millis) { @@ -1455,10 +1020,6 @@ public class VibratorService extends IVibratorService.Stub FrameworkStatsLog.write_non_chained(FrameworkStatsLog.VIBRATOR_STATE_CHANGED, uid, null, FrameworkStatsLog.VIBRATOR_STATE_CHANGED__STATE__ON, millis); mCurVibUid = uid; - if (!mIsVibrating) { - mIsVibrating = true; - notifyStateListenersLocked(); - } } catch (RemoteException e) { } } @@ -1472,22 +1033,6 @@ public class VibratorService extends IVibratorService.Stub } catch (RemoteException e) { } mCurVibUid = -1; } - if (mIsVibrating) { - mIsVibrating = false; - notifyStateListenersLocked(); - } - } - - private void setVibratorUnderExternalControl(boolean externalControl) { - if (DEBUG) { - if (externalControl) { - Slog.d(TAG, "Vibrator going under external control."); - } else { - Slog.d(TAG, "Taking back control of vibrator."); - } - } - mVibratorUnderExternalControl = externalControl; - mNativeWrapper.vibratorSetExternalControl(externalControl); } private void dumpInternal(PrintWriter pw) { @@ -1495,48 +1040,43 @@ public class VibratorService extends IVibratorService.Stub synchronized (mLock) { pw.print(" mCurrentVibration="); if (mCurrentVibration != null) { - pw.println(mCurrentVibration.toInfo().toString()); + pw.println(mCurrentVibration.getDebugInfo().toString()); } else { pw.println("null"); } pw.print(" mCurrentExternalVibration="); if (mCurrentExternalVibration != null) { - pw.println(mCurrentExternalVibration.toInfo().toString()); + pw.println(mCurrentExternalVibration.getDebugInfo().toString()); } else { pw.println("null"); } - pw.println(" mVibratorUnderExternalControl=" + mVibratorUnderExternalControl); - pw.println(" mIsVibrating=" + mIsVibrating); - pw.println(" mVibratorStateListeners Count=" - + mVibratorStateListeners.getRegisteredCallbackCount()); pw.println(" mLowPowerMode=" + mLowPowerMode); + pw.println(" mVibratorController=" + mVibratorController); pw.println(" mVibrationSettings=" + mVibrationSettings); - pw.println(" mSupportedEffects=" + mSupportedEffects); - pw.println(" mSupportedPrimitives=" + mSupportedPrimitives); pw.println(); pw.println(" Previous ring vibrations:"); - for (VibrationInfo info : mPreviousRingVibrations) { + for (Vibration.DebugInfo info : mPreviousRingVibrations) { pw.print(" "); pw.println(info.toString()); } pw.println(" Previous notification vibrations:"); - for (VibrationInfo info : mPreviousNotificationVibrations) { + for (Vibration.DebugInfo info : mPreviousNotificationVibrations) { pw.println(" " + info); } pw.println(" Previous alarm vibrations:"); - for (VibrationInfo info : mPreviousAlarmVibrations) { + for (Vibration.DebugInfo info : mPreviousAlarmVibrations) { pw.println(" " + info); } pw.println(" Previous vibrations:"); - for (VibrationInfo info : mPreviousVibrations) { + for (Vibration.DebugInfo info : mPreviousVibrations) { pw.println(" " + info); } pw.println(" Previous external vibrations:"); - for (VibrationInfo info : mPreviousExternalVibrations) { + for (Vibration.DebugInfo info : mPreviousExternalVibrations) { pw.println(" " + info); } } @@ -1547,16 +1087,16 @@ public class VibratorService extends IVibratorService.Stub synchronized (mLock) { if (mCurrentVibration != null) { - mCurrentVibration.toInfo().dumpProto(proto, + mCurrentVibration.getDebugInfo().dumpProto(proto, VibratorServiceDumpProto.CURRENT_VIBRATION); } if (mCurrentExternalVibration != null) { - mCurrentExternalVibration.toInfo().dumpProto(proto, + mCurrentExternalVibration.getDebugInfo().dumpProto(proto, VibratorServiceDumpProto.CURRENT_EXTERNAL_VIBRATION); } - proto.write(VibratorServiceDumpProto.IS_VIBRATING, mIsVibrating); + proto.write(VibratorServiceDumpProto.IS_VIBRATING, mVibratorController.isVibrating()); proto.write(VibratorServiceDumpProto.VIBRATOR_UNDER_EXTERNAL_CONTROL, - mVibratorUnderExternalControl); + mVibratorController.isUnderExternalControl()); proto.write(VibratorServiceDumpProto.LOW_POWER_MODE, mLowPowerMode); proto.write(VibratorServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY, mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_TOUCH)); @@ -1571,23 +1111,23 @@ public class VibratorService extends IVibratorService.Stub proto.write(VibratorServiceDumpProto.RING_DEFAULT_INTENSITY, mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE)); - for (VibrationInfo info : mPreviousRingVibrations) { + for (Vibration.DebugInfo info : mPreviousRingVibrations) { info.dumpProto(proto, VibratorServiceDumpProto.PREVIOUS_RING_VIBRATIONS); } - for (VibrationInfo info : mPreviousNotificationVibrations) { + for (Vibration.DebugInfo info : mPreviousNotificationVibrations) { info.dumpProto(proto, VibratorServiceDumpProto.PREVIOUS_NOTIFICATION_VIBRATIONS); } - for (VibrationInfo info : mPreviousAlarmVibrations) { + for (Vibration.DebugInfo info : mPreviousAlarmVibrations) { info.dumpProto(proto, VibratorServiceDumpProto.PREVIOUS_ALARM_VIBRATIONS); } - for (VibrationInfo info : mPreviousVibrations) { + for (Vibration.DebugInfo info : mPreviousVibrations) { info.dumpProto(proto, VibratorServiceDumpProto.PREVIOUS_VIBRATIONS); } - for (VibrationInfo info : mPreviousExternalVibrations) { + for (Vibration.DebugInfo info : mPreviousExternalVibrations) { info.dumpProto(proto, VibratorServiceDumpProto.PREVIOUS_EXTERNAL_VIBRATIONS); } } @@ -1602,9 +1142,9 @@ public class VibratorService extends IVibratorService.Stub private boolean mForceStop; VibrateWaveformThread(Vibration vib) { - mWaveform = (VibrationEffect.Waveform) vib.effect; - mVibration = new Vibration(vib.token, /* effect= */ null, vib.attrs, vib.uid, - vib.opPkg, vib.reason); + mWaveform = (VibrationEffect.Waveform) vib.getEffect(); + mVibration = new Vibration(vib.token, /* id= */ 0, /* effect= */ null, vib.attrs, + vib.uid, vib.opPkg, vib.reason); mTmpWorkSource.set(vib.uid); mWakeLock.setWorkSource(mTmpWorkSource); } @@ -1676,13 +1216,13 @@ public class VibratorService extends IVibratorService.Stub // appropriate intervals. long onDuration = getTotalOnDuration( timings, amplitudes, index - 1, repeat); - mVibration.effect = VibrationEffect.createOneShot( - onDuration, amplitude); + mVibration.updateEffect( + VibrationEffect.createOneShot(onDuration, amplitude)); doVibratorOn(mVibration); nextVibratorStopTime = now + onDuration; } else { // Vibrator is already ON, so just change its amplitude. - doVibratorSetAmplitude(amplitude); + mVibratorController.setAmplitude(amplitude); } } else { // Previous vibration should have already finished, but we make sure @@ -1744,95 +1284,12 @@ public class VibratorService extends IVibratorService.Stub } } - /** Wrapper around the static-native methods of {@link VibratorService} for tests. */ - @VisibleForTesting - public static class NativeWrapper { - - private long mNativeServicePtr = 0; - - /** Checks if vibrator exists on device. */ - public boolean vibratorExists() { - return VibratorService.vibratorExists(mNativeServicePtr); - } - - /** Initializes connection to vibrator HAL service. */ - public void vibratorInit(OnCompleteListener listener) { - mNativeServicePtr = VibratorService.vibratorInit(listener); - long finalizerPtr = VibratorService.vibratorGetFinalizer(); - - if (finalizerPtr != 0) { - NativeAllocationRegistry registry = - NativeAllocationRegistry.createMalloced( - VibratorService.class.getClassLoader(), finalizerPtr); - registry.registerNativeAllocation(this, mNativeServicePtr); - } - } - - /** Turns vibrator on for given time. */ - public void vibratorOn(long milliseconds, long vibrationId) { - VibratorService.vibratorOn(mNativeServicePtr, milliseconds, vibrationId); - } - - /** Turns vibrator off. */ - public void vibratorOff() { - VibratorService.vibratorOff(mNativeServicePtr); - } - - /** Sets the amplitude for the vibrator to run. */ - public void vibratorSetAmplitude(int amplitude) { - VibratorService.vibratorSetAmplitude(mNativeServicePtr, amplitude); - } - - /** Returns all predefined effects supported by the device vibrator. */ - public int[] vibratorGetSupportedEffects() { - return VibratorService.vibratorGetSupportedEffects(mNativeServicePtr); - } - - /** Returns all compose primitives supported by the device vibrator. */ - public int[] vibratorGetSupportedPrimitives() { - return VibratorService.vibratorGetSupportedPrimitives(mNativeServicePtr); - } - - /** Turns vibrator on to perform one of the supported effects. */ - public long vibratorPerformEffect(long effect, long strength, long vibrationId) { - return VibratorService.vibratorPerformEffect( - mNativeServicePtr, effect, strength, vibrationId); - } - - /** Turns vibrator on to perform one of the supported composed effects. */ - public void vibratorPerformComposedEffect( - VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId) { - VibratorService.vibratorPerformComposedEffect(mNativeServicePtr, effect, - vibrationId); - } - - /** Enabled the device vibrator to be controlled by another service. */ - public void vibratorSetExternalControl(boolean enabled) { - VibratorService.vibratorSetExternalControl(mNativeServicePtr, enabled); - } - - /** Returns all capabilities of the device vibrator. */ - public long vibratorGetCapabilities() { - return VibratorService.vibratorGetCapabilities(mNativeServicePtr); - } - - /** Enable always-on vibration with given id and effect. */ - public void vibratorAlwaysOnEnable(long id, long effect, long strength) { - VibratorService.vibratorAlwaysOnEnable(mNativeServicePtr, id, effect, strength); - } - - /** Disable always-on vibration for given id. */ - public void vibratorAlwaysOnDisable(long id) { - VibratorService.vibratorAlwaysOnDisable(mNativeServicePtr, id); - } - } - /** Point of injection for test dependencies */ @VisibleForTesting static class Injector { - NativeWrapper getNativeWrapper() { - return new NativeWrapper(); + VibratorController createVibratorController(OnVibrationCompleteListener listener) { + return new VibratorController(/* vibratorId= */ 0, listener); } Handler createHandler(Looper looper) { @@ -1855,9 +1312,9 @@ public class VibratorService extends IVibratorService.Stub // haptic feedback as part of the transition. So we don't cancel // system vibrations. if (mCurrentVibration != null - && !(mCurrentVibration.isHapticFeedback() - && mCurrentVibration.isFromSystem())) { - doCancelVibrateLocked(VibrationInfo.Status.CANCELLED); + && !(isHapticFeedback(mCurrentVibration) + && isFromSystem(mCurrentVibration))) { + doCancelVibrateLocked(Vibration.Status.CANCELLED); } } } @@ -1898,7 +1355,7 @@ public class VibratorService extends IVibratorService.Stub @Override public int onExternalVibrationStart(ExternalVibration vib) { - if (!hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { + if (!mVibratorController.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { return IExternalVibratorService.SCALE_MUTE; } if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE, @@ -1916,9 +1373,9 @@ public class VibratorService extends IVibratorService.Stub vibHolder.scale = SCALE_MUTE; if (mode == AppOpsManager.MODE_ERRORED) { Slog.w(TAG, "Would be an error: external vibrate from uid " + vib.getUid()); - endVibrationLocked(vibHolder, VibrationInfo.Status.ERROR_APP_OPS); + endVibrationLocked(vibHolder, Vibration.Status.ERROR_APP_OPS); } else { - endVibrationLocked(vibHolder, VibrationInfo.Status.IGNORED_APP_OPS); + endVibrationLocked(vibHolder, Vibration.Status.IGNORED_APP_OPS); } return IExternalVibratorService.SCALE_MUTE; } @@ -1933,10 +1390,13 @@ public class VibratorService extends IVibratorService.Stub if (mCurrentExternalVibration == null) { // If we're not under external control right now, then cancel any normal // vibration that may be playing and ready the vibrator for external control. - doCancelVibrateLocked(VibrationInfo.Status.CANCELLED); - setVibratorUnderExternalControl(true); + if (DEBUG) { + Slog.d(TAG, "Vibrator going under external control."); + } + doCancelVibrateLocked(Vibration.Status.CANCELLED); + mVibratorController.setExternalControl(true); } else { - endVibrationLocked(mCurrentExternalVibration, VibrationInfo.Status.CANCELLED); + endVibrationLocked(mCurrentExternalVibration, Vibration.Status.CANCELLED); } // At this point we either have an externally controlled vibration playing, or // no vibration playing. Since the interface defines that only one externally @@ -1966,12 +1426,12 @@ public class VibratorService extends IVibratorService.Stub if (DEBUG) { Slog.e(TAG, "Stopping external vibration" + vib); } - doCancelExternalVibrateLocked(VibrationInfo.Status.FINISHED); + doCancelExternalVibrateLocked(Vibration.Status.FINISHED); } } } - private void doCancelExternalVibrateLocked(VibrationInfo.Status status) { + private void doCancelExternalVibrateLocked(Vibration.Status status) { Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doCancelExternalVibrateLocked"); try { if (mCurrentExternalVibration == null) { @@ -1982,7 +1442,7 @@ public class VibratorService extends IVibratorService.Stub mCurrentExternalDeathRecipient); mCurrentExternalDeathRecipient = null; mCurrentExternalVibration = null; - setVibratorUnderExternalControl(false); + mVibratorController.setExternalControl(false); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); } @@ -1995,7 +1455,7 @@ public class VibratorService extends IVibratorService.Stub if (DEBUG) { Slog.d(TAG, "External vibration finished because binder died"); } - doCancelExternalVibrateLocked(VibrationInfo.Status.CANCELLED); + doCancelExternalVibrateLocked(Vibration.Status.CANCELLED); } } } @@ -2180,19 +1640,19 @@ public class VibratorService extends IVibratorService.Stub Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runCapabilities"); try (PrintWriter pw = getOutPrintWriter();) { pw.println("Vibrator capabilities:"); - if (hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + if (mVibratorController.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { pw.println(" Always on effects"); } - if (hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { + if (mVibratorController.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { pw.println(" Compose effects"); } - if (hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { + if (mVibratorController.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { pw.println(" Amplitude control"); } - if (hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { + if (mVibratorController.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { pw.println(" External control"); } - if (hasCapability(IVibrator.CAP_EXTERNAL_AMPLITUDE_CONTROL)) { + if (mVibratorController.hasCapability(IVibrator.CAP_EXTERNAL_AMPLITUDE_CONTROL)) { pw.println(" External amplitude control"); } pw.println(""); diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index a9f62d91592d..3270dd55218c 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -132,6 +132,16 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // TODO: make this private with a getter. public NetworkCapabilities networkCapabilities; public final NetworkAgentConfig networkAgentConfig; + + // Underlying networks declared by the agent. Only set if supportsUnderlyingNetworks is true. + // The networks in this list might be declared by a VPN app using setUnderlyingNetworks and are + // not guaranteed to be current or correct, or even to exist. + public @Nullable Network[] declaredUnderlyingNetworks; + + // Whether this network is always metered even if its underlying networks are unmetered. + // Only relevant if #supportsUnderlyingNetworks is true. + public boolean declaredMetered; + // Indicates if netd has been told to create this Network. From this point on the appropriate // routing rules are setup and routes are added so packets can begin flowing over the Network. // This is a sticky bit; once set it is never cleared. @@ -474,10 +484,16 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { networkCapabilities); } + /** Whether this network is a VPN. */ public boolean isVPN() { return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN); } + /** Whether this network might have underlying networks. Currently only true for VPNs. */ + public boolean supportsUnderlyingNetworks() { + return isVPN(); + } + private int getCurrentScore(boolean pretendValidated) { // TODO: We may want to refactor this into a NetworkScore class that takes a base score from // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index bdd315de32b1..234dcc9d74a5 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -112,7 +112,6 @@ import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnInfo; import com.android.internal.net.VpnProfile; import com.android.internal.util.ArrayUtils; -import com.android.server.ConnectivityService; import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; import com.android.server.net.BaseNetworkObserver; @@ -123,7 +122,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.math.BigInteger; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; @@ -153,36 +151,13 @@ import java.util.concurrent.atomic.AtomicInteger; public class Vpn { private static final String NETWORKTYPE = "VPN"; private static final String TAG = "Vpn"; + private static final String VPN_PROVIDER_NAME_BASE = "VpnNetworkProvider:"; private static final boolean LOGD = true; // Length of time (in milliseconds) that an app hosting an always-on VPN is placed on // the device idle allowlist during service launch and VPN bootstrap. private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000; - // Settings for how much of the address space should be routed so that Vpn considers - // "most" of the address space is routed. This is used to determine whether this Vpn - // should be marked with the INTERNET capability. - private static final long MOST_IPV4_ADDRESSES_COUNT; - private static final BigInteger MOST_IPV6_ADDRESSES_COUNT; - static { - // 85% of the address space must be routed for Vpn to consider this VPN to provide - // INTERNET access. - final int howManyPercentIsMost = 85; - - final long twoPower32 = 1L << 32; - MOST_IPV4_ADDRESSES_COUNT = twoPower32 * howManyPercentIsMost / 100; - final BigInteger twoPower128 = BigInteger.ONE.shiftLeft(128); - MOST_IPV6_ADDRESSES_COUNT = twoPower128 - .multiply(BigInteger.valueOf(howManyPercentIsMost)) - .divide(BigInteger.valueOf(100)); - } - // How many routes to evaluate before bailing and declaring this Vpn should provide - // the INTERNET capability. This is necessary because computing the address space is - // O(n²) and this is running in the system service, so a limit is needed to alleviate - // the risk of attack. - // This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm - // is actually O(n²)+O(n²). - private static final int MAX_ROUTES_TO_EVALUATE = 150; private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME = Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST; /** @@ -199,6 +174,7 @@ public class Vpn { // automated reconnection private final Context mContext; + private final ConnectivityManager mConnectivityManager; // The context is for specific user which is created from mUserId private final Context mUserIdContext; @VisibleForTesting final Dependencies mDeps; @@ -219,6 +195,7 @@ public class Vpn { private final INetworkManagementService mNetd; @VisibleForTesting protected VpnConfig mConfig; + private final NetworkProvider mNetworkProvider; @VisibleForTesting protected NetworkAgent mNetworkAgent; private final Looper mLooper; @@ -402,6 +379,7 @@ public class Vpn { int userId, @NonNull KeyStore keyStore, SystemServices systemServices, Ikev2SessionCreator ikev2SessionCreator) { mContext = context; + mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); mDeps = deps; mNetd = netService; @@ -420,13 +398,16 @@ public class Vpn { Log.wtf(TAG, "Problem registering observer", e); } + mNetworkProvider = new NetworkProvider(context, looper, VPN_PROVIDER_NAME_BASE + mUserId); + // This constructor is called in onUserStart and registers the provider. The provider + // will be unregistered in onUserStop. + mConnectivityManager.registerNetworkProvider(mNetworkProvider); mLegacyState = LegacyVpnInfo.STATE_DISCONNECTED; mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_VPN, 0 /* subtype */, NETWORKTYPE, "" /* subtypeName */); mNetworkCapabilities = new NetworkCapabilities(); mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN); mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN); - updateCapabilities(null /* defaultNetwork */); loadAlwaysOnPackage(keyStore); } @@ -444,12 +425,39 @@ public class Vpn { * Update current state, dispatching event to listeners. */ @VisibleForTesting + @GuardedBy("this") protected void updateState(DetailedState detailedState, String reason) { if (LOGD) Log.d(TAG, "setting state=" + detailedState + ", reason=" + reason); mLegacyState = LegacyVpnInfo.stateFromNetworkInfo(detailedState); mNetworkInfo.setDetailedState(detailedState, reason, null); - if (mNetworkAgent != null) { - mNetworkAgent.sendNetworkInfo(mNetworkInfo); + // TODO : only accept transitions when the agent is in the correct state (non-null for + // CONNECTED, DISCONNECTED and FAILED, null for CONNECTED). + // This will require a way for tests to pretend the VPN is connected that's not + // calling this method with CONNECTED. + // It will also require audit of where the code calls this method with DISCONNECTED + // with a null agent, which it was doing historically to make sure the agent is + // disconnected as this was a no-op if the agent was null. + switch (detailedState) { + case CONNECTED: + if (null != mNetworkAgent) { + mNetworkAgent.markConnected(); + } + break; + case DISCONNECTED: + case FAILED: + if (null != mNetworkAgent) { + mNetworkAgent.unregister(); + mNetworkAgent = null; + } + break; + case CONNECTING: + if (null != mNetworkAgent) { + throw new IllegalStateException("VPN can only go to CONNECTING state when" + + " the agent is null."); + } + break; + default: + throw new IllegalArgumentException("Illegal state argument " + detailedState); } updateAlwaysOnNotification(detailedState); } @@ -477,7 +485,7 @@ public class Vpn { final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered; applyUnderlyingCapabilities( - mContext.getSystemService(ConnectivityManager.class), + mConnectivityManager, underlyingNetworks, mNetworkCapabilities, isAlwaysMetered); @@ -487,10 +495,10 @@ public class Vpn { @VisibleForTesting public static void applyUnderlyingCapabilities( - ConnectivityManager cm, - Network[] underlyingNetworks, - NetworkCapabilities caps, - boolean isAlwaysMetered) { + @NonNull final ConnectivityManager cm, + @Nullable final Network[] underlyingNetworks, + @NonNull final NetworkCapabilities caps, + final boolean isAlwaysMetered) { int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN }; int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; @@ -1017,7 +1025,7 @@ public class Vpn { } mConfig = null; - updateState(DetailedState.IDLE, "prepare"); + updateState(DetailedState.DISCONNECTED, "prepare"); setVpnForcedLocked(mLockdown); } finally { Binder.restoreCallingIdentity(token); @@ -1253,7 +1261,7 @@ public class Vpn { mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); mLegacyState = LegacyVpnInfo.STATE_CONNECTING; - mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null); + updateState(DetailedState.CONNECTING, "agentConnect"); NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown; @@ -1262,20 +1270,34 @@ public class Vpn { mNetworkCapabilities.setAdministratorUids(new int[] {mOwnerUID}); mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserId, mConfig.allowedApplications, mConfig.disallowedApplications)); - final long token = Binder.clearCallingIdentity(); - try { - mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */, - mNetworkInfo, mNetworkCapabilities, lp, - ConnectivityConstants.VPN_DEFAULT_SCORE, networkAgentConfig, - NetworkProvider.ID_VPN) { - @Override - public void unwanted() { - // We are user controlled, not driven by NetworkRequest. - } - }; - } finally { - Binder.restoreCallingIdentity(token); + + // Only apps targeting Q and above can explicitly declare themselves as metered. + // These VPNs are assumed metered unless they state otherwise. + if (mIsPackageTargetingAtLeastQ && mConfig.isMetered) { + mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_METERED); + } else { + mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); } + + mNetworkAgent = new NetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */, + mNetworkCapabilities, lp, + ConnectivityConstants.VPN_DEFAULT_SCORE, networkAgentConfig, mNetworkProvider) { + @Override + public void unwanted() { + // We are user controlled, not driven by NetworkRequest. + } + }; + Binder.withCleanCallingIdentity(() -> { + try { + mNetworkAgent.register(); + } catch (final Exception e) { + // If register() throws, don't keep an unregistered agent. + mNetworkAgent = null; + throw e; + } + }); + mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null) + ? Arrays.asList(mConfig.underlyingNetworks) : null); mNetworkInfo.setIsAvailable(true); updateState(DetailedState.CONNECTED, "agentConnect"); } @@ -1291,19 +1313,12 @@ public class Vpn { private void agentDisconnect(NetworkAgent networkAgent) { if (networkAgent != null) { - NetworkInfo networkInfo = new NetworkInfo(mNetworkInfo); - networkInfo.setIsAvailable(false); - networkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); - networkAgent.sendNetworkInfo(networkInfo); + networkAgent.unregister(); } } private void agentDisconnect() { - if (mNetworkInfo.isConnected()) { - mNetworkInfo.setIsAvailable(false); - updateState(DetailedState.DISCONNECTED, "agentDisconnect"); - mNetworkAgent = null; - } + updateState(DetailedState.DISCONNECTED, "agentDisconnect"); } /** @@ -1392,6 +1407,8 @@ public class Vpn { && updateLinkPropertiesInPlaceIfPossible(mNetworkAgent, oldConfig)) { // Keep mNetworkAgent unchanged } else { + // Initialize the state for a new agent, while keeping the old one connected + // in case this new connection fails. mNetworkAgent = null; updateState(DetailedState.CONNECTING, "establish"); // Set up forwarding and DNS rules. @@ -1575,12 +1592,13 @@ public class Vpn { try { addUserToRanges(existingRanges, userId, mConfig.allowedApplications, mConfig.disallowedApplications); - // ConnectivityService will call {@link #updateCapabilities} and apply - // those for VPN network. mNetworkCapabilities.setUids(existingRanges); } catch (Exception e) { Log.wtf(TAG, "Failed to add restricted user to owner", e); } + if (mNetworkAgent != null) { + mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); + } } setVpnForcedLocked(mLockdown); } @@ -1603,12 +1621,13 @@ public class Vpn { final List<UidRange> removedRanges = uidRangesForUser(userId, existingRanges); existingRanges.removeAll(removedRanges); - // ConnectivityService will call {@link #updateCapabilities} and - // apply those for VPN network. mNetworkCapabilities.setUids(existingRanges); } catch (Exception e) { Log.wtf(TAG, "Failed to remove restricted user to owner", e); } + if (mNetworkAgent != null) { + mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); + } } setVpnForcedLocked(mLockdown); } @@ -1625,6 +1644,9 @@ public class Vpn { // Quit any active connections agentDisconnect(); + + // The provider has been registered in the constructor, which is called in onUserStart. + mConnectivityManager.unregisterNetworkProvider(mNetworkProvider); } /** @@ -1857,6 +1879,8 @@ public class Vpn { } } } + mNetworkAgent.setUnderlyingNetworks((mConfig.underlyingNetworks != null) + ? Arrays.asList(mConfig.underlyingNetworks) : null); return true; } @@ -2399,7 +2423,6 @@ public class Vpn { // When restricted to test networks, select any network with TRANSPORT_TEST. Since the // creator of the profile and the test network creator both have MANAGE_TEST_NETWORKS, // this is considered safe. - final ConnectivityManager cm = ConnectivityManager.from(mContext); final NetworkRequest req; if (mProfile.isRestrictedToTestNetworks()) { @@ -2418,7 +2441,7 @@ public class Vpn { .build(); } - cm.requestNetwork(req, mNetworkCallback); + mConnectivityManager.requestNetwork(req, mNetworkCallback); } private boolean isActiveNetwork(@Nullable Network network) { @@ -2705,8 +2728,7 @@ public class Vpn { resetIkeState(); - final ConnectivityManager cm = ConnectivityManager.from(mContext); - cm.unregisterNetworkCallback(mNetworkCallback); + mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); mExecutor.shutdown(); } @@ -2787,13 +2809,12 @@ public class Vpn { mProfile = profile; if (!TextUtils.isEmpty(mOuterInterface)) { - final ConnectivityManager cm = ConnectivityManager.from(mContext); - for (Network network : cm.getAllNetworks()) { - final LinkProperties lp = cm.getLinkProperties(network); + for (Network network : mConnectivityManager.getAllNetworks()) { + final LinkProperties lp = mConnectivityManager.getLinkProperties(network); if (lp != null && lp.getAllInterfaceNames().contains(mOuterInterface)) { - final NetworkInfo networkInfo = cm.getNetworkInfo(network); - if (networkInfo != null) { - mOuterConnection.set(networkInfo.getType()); + final NetworkInfo netInfo = mConnectivityManager.getNetworkInfo(network); + if (netInfo != null) { + mOuterConnection.set(netInfo.getType()); break; } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java index 0566d32160fc..2374ece1dd65 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java @@ -22,12 +22,19 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringDef; +import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; +import android.database.ContentObserver; import android.hardware.hdmi.HdmiControlManager; +import android.net.Uri; import android.os.Environment; +import android.os.Handler; +import android.os.Looper; import android.os.SystemProperties; +import android.os.UserHandle; import android.provider.Settings.Global; +import android.util.ArrayMap; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; @@ -85,9 +92,26 @@ public class HdmiCecConfig { @NonNull private final Context mContext; @NonNull private final StorageAdapter mStorageAdapter; - @Nullable private final CecSettings mSystemConfig; + @Nullable private final CecSettings mProductConfig; @Nullable private final CecSettings mVendorOverride; + private final ArrayMap<Setting, Set<SettingChangeListener>> + mSettingChangeListeners = new ArrayMap<>(); + + private SettingsObserver mSettingsObserver; + + /** + * Listener used to get notifications when value of a setting changes. + */ + public interface SettingChangeListener { + /** + * Called when value of a setting changes. + * + * @param setting name of a CEC setting that changed + */ + void onChange(@NonNull @CecSettingName String setting); + } + /** * Setting storage input/output helper class. */ @@ -159,17 +183,29 @@ public class HdmiCecConfig { } } + private class SettingsObserver extends ContentObserver { + SettingsObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + String setting = uri.getLastPathSegment(); + HdmiCecConfig.this.notifyGlobalSettingChanged(setting); + } + } + @VisibleForTesting HdmiCecConfig(@NonNull Context context, @NonNull StorageAdapter storageAdapter, - @Nullable CecSettings systemConfig, + @Nullable CecSettings productConfig, @Nullable CecSettings vendorOverride) { mContext = context; mStorageAdapter = storageAdapter; - mSystemConfig = systemConfig; + mProductConfig = productConfig; mVendorOverride = vendorOverride; - if (mSystemConfig == null) { - Slog.i(TAG, "CEC system configuration XML missing."); + if (mProductConfig == null) { + Slog.i(TAG, "CEC master configuration XML missing."); } if (mVendorOverride == null) { Slog.i(TAG, "CEC OEM configuration override XML missing."); @@ -178,7 +214,7 @@ public class HdmiCecConfig { HdmiCecConfig(@NonNull Context context) { this(context, new StorageAdapter(context), - readSettingsFromFile(Environment.buildPath(Environment.getRootDirectory(), + readSettingsFromFile(Environment.buildPath(Environment.getProductDirectory(), ETC_DIR, CONFIG_FILE)), readSettingsFromFile(Environment.buildPath(Environment.getVendorDirectory(), ETC_DIR, CONFIG_FILE))); @@ -205,14 +241,14 @@ public class HdmiCecConfig { @VisibleForTesting static HdmiCecConfig createFromStrings(@NonNull Context context, @NonNull StorageAdapter storageAdapter, - @Nullable String systemConfigXml, + @Nullable String productConfigXml, @Nullable String vendorOverrideXml) { - CecSettings systemConfig = null; + CecSettings productConfig = null; CecSettings vendorOverride = null; try { - if (systemConfigXml != null) { - systemConfig = XmlParser.read( - new ByteArrayInputStream(systemConfigXml.getBytes())); + if (productConfigXml != null) { + productConfig = XmlParser.read( + new ByteArrayInputStream(productConfigXml.getBytes())); } if (vendorOverrideXml != null) { vendorOverride = XmlParser.read( @@ -221,12 +257,12 @@ public class HdmiCecConfig { } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) { Slog.e(TAG, "Encountered an error while reading/parsing CEC config strings", e); } - return new HdmiCecConfig(context, storageAdapter, systemConfig, vendorOverride); + return new HdmiCecConfig(context, storageAdapter, productConfig, vendorOverride); } @Nullable private Setting getSetting(@NonNull String name) { - if (mSystemConfig == null) { + if (mProductConfig == null) { return null; } if (mVendorOverride != null) { @@ -237,8 +273,8 @@ public class HdmiCecConfig { } } } - // If not found, try the system config. - for (Setting setting : mSystemConfig.getSetting()) { + // If not found, try the product config. + for (Setting setting : mProductConfig.getSetting()) { if (setting.getName().equals(name)) { return setting; } @@ -311,6 +347,7 @@ public class HdmiCecConfig { } else if (storage == STORAGE_SHARED_PREFS) { Slog.d(TAG, "Setting '" + storageKey + "' shared pref."); mStorageAdapter.storeSharedPref(storageKey, value); + notifySettingChanged(setting); } } @@ -318,15 +355,112 @@ public class HdmiCecConfig { return Integer.decode(value.getIntValue()); } + private void notifyGlobalSettingChanged(String setting) { + switch (setting) { + case Global.HDMI_CONTROL_ENABLED: + notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED); + break; + case Global.HDMI_CEC_VERSION: + notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION); + break; + case Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP: + notifySettingChanged(HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP); + break; + } + } + + private void notifySettingChanged(@NonNull @CecSettingName String name) { + Setting setting = getSetting(name); + if (setting == null) { + throw new IllegalArgumentException("Setting '" + name + "' does not exist."); + } + notifySettingChanged(setting); + } + + private void notifySettingChanged(@NonNull Setting setting) { + Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting); + if (listeners == null) { + return; // No listeners registered, do nothing. + } + for (SettingChangeListener listener: listeners) { + listener.onChange(setting.getName()); + } + } + + /** + * This method registers Global Setting change observer. + * Needs to be called once after initialization of HdmiCecConfig. + */ + public void registerGlobalSettingsObserver(Looper looper) { + Handler handler = new Handler(looper); + mSettingsObserver = new SettingsObserver(handler); + ContentResolver resolver = mContext.getContentResolver(); + String[] settings = new String[] { + Global.HDMI_CONTROL_ENABLED, + Global.HDMI_CEC_VERSION, + Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP, + }; + for (String setting: settings) { + resolver.registerContentObserver(Global.getUriFor(setting), false, + mSettingsObserver, UserHandle.USER_ALL); + } + } + + /** + * This method unregisters Global Setting change observer. + */ + public void unregisterGlobalSettingsObserver() { + ContentResolver resolver = mContext.getContentResolver(); + resolver.unregisterContentObserver(mSettingsObserver); + } + + /** + * Register change listener for a given setting name. + */ + public void registerChangeListener(@NonNull @CecSettingName String name, + SettingChangeListener listener) { + Setting setting = getSetting(name); + if (setting == null) { + throw new IllegalArgumentException("Setting '" + name + "' does not exist."); + } + @Storage int storage = getStorage(setting); + if (storage != STORAGE_GLOBAL_SETTINGS && storage != STORAGE_SHARED_PREFS) { + throw new IllegalArgumentException("Change listeners for setting '" + name + + "' not supported."); + } + if (!mSettingChangeListeners.containsKey(setting)) { + mSettingChangeListeners.put(setting, new HashSet<>()); + } + mSettingChangeListeners.get(setting).add(listener); + } + + /** + * Remove change listener for a given setting name. + */ + public void removeChangeListener(@NonNull @CecSettingName String name, + SettingChangeListener listener) { + Setting setting = getSetting(name); + if (setting == null) { + throw new IllegalArgumentException("Setting '" + name + "' does not exist."); + } + if (mSettingChangeListeners.containsKey(setting)) { + Set<SettingChangeListener> listeners = mSettingChangeListeners.get(setting); + listeners.remove(listener); + if (listeners.isEmpty()) { + mSettingChangeListeners.remove(setting); + } + } + } + /** * Returns a list of all settings based on the XML metadata. */ public @CecSettingName List<String> getAllSettings() { - if (mSystemConfig == null) { + if (mProductConfig == null) { return new ArrayList<String>(); } List<String> allSettings = new ArrayList<String>(); - for (Setting setting : mSystemConfig.getSetting()) { + for (Setting setting : mProductConfig.getSetting()) { allSettings.add(setting.getName()); } return allSettings; @@ -336,12 +470,12 @@ public class HdmiCecConfig { * Returns a list of user-modifiable settings based on the XML metadata. */ public @CecSettingName List<String> getUserSettings() { - if (mSystemConfig == null) { + if (mProductConfig == null) { return new ArrayList<String>(); } Set<String> userSettings = new HashSet<String>(); - // First read from the system config. - for (Setting setting : mSystemConfig.getSetting()) { + // First read from the product config. + for (Setting setting : mProductConfig.getSetting()) { if (setting.getUserConfigurable()) { userSettings.add(setting.getName()); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 1cbbe2dc5b6a..9b3f788d7457 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -566,6 +566,11 @@ abstract class HdmiCecLocalDevice { return false; } + reportFeatures(); + return true; + } + + protected void reportFeatures() { List<Integer> localDeviceTypes = new ArrayList<>(); for (HdmiCecLocalDevice localDevice : mService.getAllLocalDevices()) { localDeviceTypes.add(localDevice.mDeviceType); @@ -579,7 +584,6 @@ abstract class HdmiCecLocalDevice { mService.sendCecCommand( HdmiCecMessageBuilder.buildReportFeatures(mAddress, mService.getCecVersion(), localDeviceTypes, rcProfile, rcFeatures, deviceFeatures)); - return true; } @ServiceThreadOnly @@ -791,6 +795,9 @@ abstract class HdmiCecLocalDevice { final void handleAddressAllocated(int logicalAddress, int reason) { assertRunOnServiceThread(); mAddress = mPreferredAddress = logicalAddress; + if (mService.getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0) { + reportFeatures(); + } onAddressAllocated(logicalAddress, reason); setPreferredAddress(logicalAddress); } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 01ec3b4cd823..fd825d6f6288 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -563,6 +563,7 @@ public class HdmiControlService extends SystemService { if (mMessageValidator == null) { mMessageValidator = new HdmiCecMessageValidator(this); } + mHdmiCecConfig.registerGlobalSettingsObserver(mIoLooper); } private void bootCompleted() { diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index cfb5116c47f3..0ceaf7748eba 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -15,6 +15,7 @@ package com.android.server.inputmethod; +import static android.inputmethodservice.InputMethodService.FINISH_INPUT_NO_FALLBACK_CONNECTION; import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL; import static android.os.IServiceManager.DUMP_FLAG_PROTO; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; @@ -45,6 +46,8 @@ import static android.server.inputmethod.InputMethodManagerServiceProto.SYSTEM_R import static android.util.imetracing.ImeTracing.IME_TRACING_FROM_IMMS; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.view.WindowManager.DISPLAY_IME_POLICY_HIDE; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -118,7 +121,6 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; import android.util.IndentingPrintWriter; -import android.util.Log; import android.util.LruCache; import android.util.Pair; import android.util.PrintWriterPrinter; @@ -131,6 +133,8 @@ import android.view.DisplayInfo; import android.view.IWindowManager; import android.view.InputChannel; import android.view.View; +import android.view.WindowManager; +import android.view.WindowManager.DisplayImePolicy; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.autofill.AutofillId; @@ -152,6 +156,7 @@ import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import com.android.internal.annotations.GuardedBy; +import com.android.internal.compat.IPlatformCompat; import com.android.internal.content.PackageMonitor; import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; @@ -531,6 +536,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub int mCurSeq; /** + * {@code true} if the Ime policy has been set to {@link WindowManager#DISPLAY_IME_POLICY_HIDE}. + * + * This prevents the IME from showing when it otherwise may have shown. + */ + boolean mImeHiddenByDisplayPolicy; + + /** * The client that is currently bound to an input method. */ ClientState mCurClient; @@ -709,6 +721,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ boolean mIsInteractive = true; + private IPlatformCompat mPlatformCompat; + int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; /** @@ -1658,7 +1672,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); - mImeDisplayValidator = displayId -> mWindowManagerInternal.shouldShowIme(displayId); + mImeDisplayValidator = displayId -> mWindowManagerInternal.getDisplayImePolicy(displayId); mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() { @Override public void executeMessage(Message msg) { @@ -1670,6 +1684,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mHasFeature = context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_INPUT_METHODS); + mPlatformCompat = IPlatformCompat.Stub.asInterface( + ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime); mIsLowRam = ActivityManager.isLowRamDeviceStatic(); @@ -2306,8 +2322,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO( - MSG_SET_ACTIVE, 0, 0, mCurClient)); + scheduleSetActiveToClient(mCurClient, false /* active */, false /* fullscreen */, + false /* reportToImeController */); executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO( MSG_UNBIND_CLIENT, mCurSeq, unbindClientReason, mCurClient.client)); mCurClient.sessionRequested = false; @@ -2438,6 +2454,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final int displayIdToShowIme = computeImeDisplayIdForTarget(cs.selfReportedDisplayId, mImeDisplayValidator); + if (displayIdToShowIme == INVALID_DISPLAY) { + mImeHiddenByDisplayPolicy = true; + return InputBindResult.NO_IME; + } + mImeHiddenByDisplayPolicy = false; + if (mCurClient != cs) { // Was the keyguard locked when switching over to the new client? mCurClientInKeyguard = isKeyguardLocked(); @@ -2449,7 +2471,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // If the screen is on, inform the new client it is active if (mIsInteractive) { - executeOrSendMessage(cs.client, mCaller.obtainMessageIO(MSG_SET_ACTIVE, 1, cs)); + scheduleSetActiveToClient(cs, true /* active */, false /* fullscreen */, + false /* reportToImeController */); } } @@ -2549,7 +2572,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @FunctionalInterface interface ImeDisplayValidator { - boolean displayCanShowIme(int displayId); + @DisplayImePolicy int getDisplayImePolicy(int displayId); } /** @@ -2558,7 +2581,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub * @param displayId the ID of the display where the IME client target is. * @param checker instance of {@link ImeDisplayValidator} which is used for * checking display config to adjust the final target display. - * @return The ID of the display where the IME should be shown. + * @return The ID of the display where the IME should be shown or + * {@link android.view.Display#INVALID_DISPLAY} if the display has an ImePolicy of + * {@link WindowManager#DISPLAY_IME_POLICY_HIDE}. */ static int computeImeDisplayIdForTarget(int displayId, @NonNull ImeDisplayValidator checker) { if (displayId == DEFAULT_DISPLAY || displayId == INVALID_DISPLAY) { @@ -2567,7 +2592,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Show IME window on fallback display when the display doesn't support system decorations // or the display is virtual and isn't owned by system for security concern. - return checker.displayCanShowIme(displayId) ? displayId : FALLBACK_DISPLAY_ID; + final int result = checker.getDisplayImePolicy(displayId); + if (result == DISPLAY_IME_POLICY_LOCAL) { + return displayId; + } else if (result == DISPLAY_IME_POLICY_HIDE) { + return INVALID_DISPLAY; + } else { + return FALLBACK_DISPLAY_ID; + } } @AnyThread @@ -4077,6 +4109,44 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return ImeTracing.getInstance().isEnabled(); } + @BinderThread + @Override + public void startImeTrace() { + ImeTracing.getInstance().startTrace(null /* printwriter */); + ArrayMap<IBinder, ClientState> clients; + synchronized (mMethodMap) { + clients = new ArrayMap<>(mClients); + } + for (ClientState state : clients.values()) { + if (state != null) { + try { + state.client.setImeTraceEnabled(true /* enabled */); + } catch (RemoteException e) { + Slog.e(TAG, "Error while trying to enable ime trace on client window", e); + } + } + } + } + + @BinderThread + @Override + public void stopImeTrace() { + ImeTracing.getInstance().stopTrace(null /* printwriter */); + ArrayMap<IBinder, ClientState> clients; + synchronized (mMethodMap) { + clients = new ArrayMap<>(mClients); + } + for (ClientState state : clients.values()) { + if (state != null) { + try { + state.client.setImeTraceEnabled(false /* enabled */); + } catch (RemoteException e) { + Slog.e(TAG, "Error while trying to disable ime trace on client window", e); + } + } + } + } + @GuardedBy("mMethodMap") private void dumpDebug(ProtoOutputStream proto, long fieldId) { synchronized (mMethodMap) { @@ -4452,15 +4522,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub args.recycle(); return true; } - case MSG_SET_ACTIVE: + case MSG_SET_ACTIVE: { + args = (SomeArgs) msg.obj; + final ClientState clientState = (ClientState) args.arg1; try { - ((ClientState)msg.obj).client.setActive(msg.arg1 != 0, msg.arg2 != 0); + clientState.client.setActive(args.argi1 != 0 /* active */, + args.argi2 != 0 /* fullScreen */, + args.argi3 != 0 /* reportToImeController */); } catch (RemoteException e) { Slog.w(TAG, "Got RemoteException sending setActive(false) notification to pid " - + ((ClientState)msg.obj).pid + " uid " - + ((ClientState)msg.obj).uid); + + clientState.pid + " uid " + clientState.uid); } + args.recycle(); return true; + } case MSG_SET_INTERACTIVE: handleSetInteractive(msg.arg1 != 0); return true; @@ -4546,13 +4621,24 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Inform the current client of the change in active status if (mCurClient != null && mCurClient.client != null) { - executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO( - MSG_SET_ACTIVE, mIsInteractive ? 1 : 0, mInFullscreenMode ? 1 : 0, - mCurClient)); + boolean reportToImeController = false; + try { + reportToImeController = mPlatformCompat.isChangeEnabledByUid( + FINISH_INPUT_NO_FALLBACK_CONNECTION, mCurMethodUid); + } catch (RemoteException e) { + } + scheduleSetActiveToClient(mCurClient, mIsInteractive, mInFullscreenMode, + reportToImeController); } } } + private void scheduleSetActiveToClient(ClientState state, boolean active, boolean fullscreen, + boolean reportToImeController) { + executeOrSendMessage(state.client, mCaller.obtainMessageIIIIO(MSG_SET_ACTIVE, + active ? 1 : 0, fullscreen ? 1 : 0, reportToImeController ? 1 : 0, 0, state)); + } + private boolean chooseNewDefaultIMELocked() { final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME( mSettings.getEnabledInputMethodListLocked()); @@ -5181,6 +5267,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub p.println(" mInFullscreenMode=" + mInFullscreenMode); p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive); p.println(" mSettingsObserver=" + mSettingsObserver); + p.println(" mImeHiddenByDisplayPolicy=" + mImeHiddenByDisplayPolicy); p.println(" mSwitchingController:"); mSwitchingController.dump(p); p.println(" mSettings:"); @@ -5722,9 +5809,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { state.client.setImeTraceEnabled(isImeTraceEnabled); } catch (RemoteException e) { - Log.e(TAG, - "Error while trying to enable/disable ime " - + "trace on client window", e); + Slog.e(TAG, "Error while trying to enable/disable ime trace on client window", + e); } } } diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index 7af27ca46f68..62d817c22ae6 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -911,7 +911,8 @@ public final class MultiClientInputMethodManagerService { com.android.internal.R.string.input_method_binding_label) .putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( context, 0, - new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0)); + new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), + PendingIntent.FLAG_MUTABLE)); // Note: Instead of re-dispatching callback from the main thread to the worker thread // where OnWorkerThreadCallback is running, we pass the Handler object here so that @@ -1338,7 +1339,7 @@ public final class MultiClientInputMethodManagerService { switch (clientInfo.mState) { case InputMethodClientState.WAITING_FOR_IME_SESSION: try { - clientInfo.mClient.setActive(true, false); + clientInfo.mClient.setActive(true, false, false); } catch (RemoteException e) { // TODO(yukawa): Remove this client. return; @@ -1400,7 +1401,7 @@ public final class MultiClientInputMethodManagerService { return; } try { - clientInfo.mClient.setActive(active, false /* fullscreen */); + clientInfo.mClient.setActive(active, false /* fullscreen */, false); } catch (RemoteException e) { return; } @@ -1816,5 +1817,15 @@ public final class MultiClientInputMethodManagerService { public boolean isImeTraceEnabled() { return false; } + + @BinderThread + @Override + public void startImeTrace() { + } + + @BinderThread + @Override + public void stopImeTrace() { + } } } diff --git a/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java b/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java index 9d262e33274b..77253099d54f 100644 --- a/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java +++ b/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java @@ -117,7 +117,7 @@ final class SimulatedBinderProviderEvent { private static LocationTimeZoneEvent parseLocationTimeZoneEventArgs(ShellCommand shellCommand) { LocationTimeZoneEvent.Builder eventBuilder = new LocationTimeZoneEvent.Builder() - .setElapsedRealtimeNanos(SystemClock.elapsedRealtime()); + .setElapsedRealtimeMillis(SystemClock.elapsedRealtime()); String eventTypeString = shellCommand.getNextArgRequired(); switch (eventTypeString.toUpperCase()) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 55f9feec10d3..db5eb844f1b4 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -5717,7 +5717,8 @@ public class PackageManagerService extends IPackageManager.Stub getPackagesUsingSharedLibraryLPr(libInfo, flags, userId), (libInfo.getDependencies() == null ? null - : new ArrayList<>(libInfo.getDependencies()))); + : new ArrayList<>(libInfo.getDependencies())), + libInfo.isNative()); if (result == null) { result = new ArrayList<>(); @@ -5786,7 +5787,8 @@ public class PackageManagerService extends IPackageManager.Stub libraryInfo.getLongVersion(), libraryInfo.getType(), libraryInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr( libraryInfo, flags, userId), libraryInfo.getDependencies() == null - ? null : new ArrayList<>(libraryInfo.getDependencies())); + ? null : new ArrayList<>(libraryInfo.getDependencies()), + libraryInfo.isNative()); if (result == null) { result = new ArrayList<>(); diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java index 0a56e1343418..ab25a7c772c0 100644 --- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java +++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java @@ -94,7 +94,7 @@ public class AndroidPackageUtils { SharedLibraryInfo.TYPE_STATIC, new VersionedPackage(pkg.getManifestPackageName(), pkg.getLongVersionCode()), - null, null); + null, null, false /* isNative */); } public static SharedLibraryInfo createSharedLibraryForDynamic(AndroidPackage pkg, String name) { @@ -103,7 +103,7 @@ public class AndroidPackageUtils { SharedLibraryInfo.VERSION_UNDEFINED, SharedLibraryInfo.TYPE_DYNAMIC, new VersionedPackage(pkg.getPackageName(), pkg.getLongVersionCode()), - null, null); + null, null, false /* isNative */); } /** diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java index cc369356c1c9..9026262db897 100644 --- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java +++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java @@ -127,9 +127,11 @@ public abstract class SoftRestrictedPermissionPolicy { final boolean isWhiteListed; boolean shouldApplyRestriction; final int targetSDK; + final boolean hasLegacyExternalStorage; final boolean hasRequestedLegacyExternalStorage; - final boolean shouldPreserveLegacyExternalStorage; + final boolean hasRequestedPreserveLegacyExternalStorage; final boolean hasWriteMediaStorageGrantedForUid; + final boolean isForcedScopedStorage; if (appInfo != null) { PackageManager pm = context.getPackageManager(); @@ -137,27 +139,27 @@ public abstract class SoftRestrictedPermissionPolicy { LocalServices.getService(StorageManagerInternal.class); int flags = pm.getPermissionFlags(permission, appInfo.packageName, user); isWhiteListed = (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0; + hasLegacyExternalStorage = smInternal.hasLegacyExternalStorage(appInfo.uid); hasRequestedLegacyExternalStorage = hasUidRequestedLegacyExternalStorage( appInfo.uid, context); hasWriteMediaStorageGrantedForUid = hasWriteMediaStorageGrantedForUid( appInfo.uid, context); - shouldPreserveLegacyExternalStorage = pkg.hasPreserveLegacyExternalStorage() - && smInternal.hasLegacyExternalStorage(appInfo.uid); + hasRequestedPreserveLegacyExternalStorage = + pkg.hasPreserveLegacyExternalStorage(); targetSDK = getMinimumTargetSDK(context, appInfo, user); - shouldApplyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0 - || (targetSDK > Build.VERSION_CODES.Q - && !shouldPreserveLegacyExternalStorage) - // If the device is configured to force this app into scoped storage, - // then we should apply the restriction - || sForcedScopedStorageAppWhitelist.contains(appInfo.packageName); + shouldApplyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; + isForcedScopedStorage = sForcedScopedStorageAppWhitelist + .contains(appInfo.packageName); } else { isWhiteListed = false; shouldApplyRestriction = false; targetSDK = 0; + hasLegacyExternalStorage = false; hasRequestedLegacyExternalStorage = false; - shouldPreserveLegacyExternalStorage = false; + hasRequestedPreserveLegacyExternalStorage = false; hasWriteMediaStorageGrantedForUid = false; + isForcedScopedStorage = false; } // We have a check in PermissionPolicyService.PermissionToOpSynchroniser.setUidMode @@ -175,14 +177,53 @@ public abstract class SoftRestrictedPermissionPolicy { } @Override public boolean mayAllowExtraAppOp() { - return !shouldApplyRestriction - && (hasRequestedLegacyExternalStorage - || hasWriteMediaStorageGrantedForUid - || shouldPreserveLegacyExternalStorage); + // The only way to get LEGACY_STORAGE (if you didn't already have it) + // is that all of the following must be true: + // 1. The flag shouldn't be restricted + if (shouldApplyRestriction) { + return false; + } + + // 2. The app shouldn't be in sForcedScopedStorageAppWhitelist + if (isForcedScopedStorage) { + return false; + } + + // 3. The app has WRITE_MEDIA_STORAGE, OR + // the app already has legacy external storage or requested it, + // and is < R. + return hasWriteMediaStorageGrantedForUid + || ((hasLegacyExternalStorage || hasRequestedLegacyExternalStorage) + && targetSDK < Build.VERSION_CODES.R); } @Override public boolean mayDenyExtraAppOpIfGranted() { - return shouldApplyRestriction; + // If you're an app targeting < R, you can keep the app op for + // as long as you meet the conditions required to acquire it. + if (targetSDK < Build.VERSION_CODES.R) { + return !mayAllowExtraAppOp(); + } + + // For an app targeting R, the only way to lose LEGACY_STORAGE if you + // already had it is in one or more of the following conditions: + // 1. The flag became restricted + if (shouldApplyRestriction) { + return true; + } + + // The package is now a part of the forced scoped storage whitelist + if (isForcedScopedStorage) { + return true; + } + + // The package doesn't have WRITE_MEDIA_STORAGE, + // AND didn't request legacy storage to be preserved + if (!hasWriteMediaStorageGrantedForUid + && !hasRequestedPreserveLegacyExternalStorage) { + return true; + } + + return false; } }; } diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java index 2d51cf9a5083..63ed416f2859 100644 --- a/services/core/java/com/android/server/rollback/Rollback.java +++ b/services/core/java/com/android/server/rollback/Rollback.java @@ -141,11 +141,17 @@ class Rollback { /** * The current state of the rollback. - * ENABLING, AVAILABLE, or COMMITTED. + * ENABLING, AVAILABLE, DELETED, or COMMITTED. */ private @RollbackState int mState; /** + * The detailed description of the current state. For a DELETED state, it describes + * the reason why the rollback is deleted. + */ + private @NonNull String mStateDescription = ""; + + /** * True if we are expecting the package manager to call restoreUserData * for this rollback because it has just been committed but the rollback * has not yet been fully applied. @@ -231,7 +237,7 @@ class Rollback { * Constructs a pre-populated Rollback instance. */ Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId, - @RollbackState int state, boolean restoreUserDataInProgress, + @RollbackState int state, String stateDescription, boolean restoreUserDataInProgress, int userId, String installerPackageName, SparseIntArray extensionVersions) { this.info = info; mUserId = userId; @@ -240,6 +246,7 @@ class Rollback { mTimestamp = timestamp; mStagedSessionId = stagedSessionId; mState = state; + mStateDescription = stateDescription; mRestoreUserDataInProgress = restoreUserDataInProgress; mExtensionVersions = Objects.requireNonNull(extensionVersions); // TODO(b/120200473): Include this field during persistence. This field will be used to @@ -478,7 +485,7 @@ class Rollback { Slog.w(TAG, "Cannot make deleted rollback available."); return; } - mState = ROLLBACK_STATE_AVAILABLE; + setState(ROLLBACK_STATE_AVAILABLE, ""); mTimestamp = Instant.now(); RollbackStore.saveRollback(this); } @@ -598,7 +605,7 @@ class Rollback { // Why would we expect commit not to fail again? // TODO: Could this cause a rollback to be resurrected // if it should otherwise have expired by now? - mState = ROLLBACK_STATE_AVAILABLE; + setState(ROLLBACK_STATE_AVAILABLE, "Commit failed"); mRestoreUserDataInProgress = false; info.setCommittedSessionId(-1); sendFailure(context, statusReceiver, @@ -642,7 +649,7 @@ class Rollback { }; final LocalIntentReceiver receiver = new LocalIntentReceiver(onResult); - mState = ROLLBACK_STATE_COMMITTED; + setState(ROLLBACK_STATE_COMMITTED, ""); info.setCommittedSessionId(parentSessionId); mRestoreUserDataInProgress = true; parentSession.commit(receiver.getIntentSender()); @@ -691,7 +698,7 @@ class Rollback { * Deletes app data snapshots associated with this rollback, and moves to the DELETED state. */ @WorkerThread - void delete(AppDataRollbackHelper dataHelper) { + void delete(AppDataRollbackHelper dataHelper, @NonNull String reason) { assertInWorkerThread(); boolean containsApex = false; Set<Integer> apexUsers = new ArraySet<>(); @@ -717,7 +724,7 @@ class Rollback { } RollbackStore.deleteRollback(this); - mState = ROLLBACK_STATE_DELETED; + setState(ROLLBACK_STATE_DELETED, reason); } /** @@ -847,6 +854,7 @@ class Rollback { case Rollback.ROLLBACK_STATE_ENABLING: return "enabling"; case Rollback.ROLLBACK_STATE_AVAILABLE: return "available"; case Rollback.ROLLBACK_STATE_COMMITTED: return "committed"; + case Rollback.ROLLBACK_STATE_DELETED: return "deleted"; } throw new AssertionError("Invalid rollback state: " + state); } @@ -858,6 +866,7 @@ class Rollback { case "enabling": return Rollback.ROLLBACK_STATE_ENABLING; case "available": return Rollback.ROLLBACK_STATE_AVAILABLE; case "committed": return Rollback.ROLLBACK_STATE_COMMITTED; + case "deleted": return Rollback.ROLLBACK_STATE_DELETED; } throw new ParseException("Invalid rollback state: " + state, 0); } @@ -926,6 +935,7 @@ class Rollback { ipw.println(info.getRollbackId() + ":"); ipw.increaseIndent(); ipw.println("-state: " + getStateAsString()); + ipw.println("-stateDescription: " + mStateDescription); ipw.println("-timestamp: " + getTimestamp()); if (getStagedSessionId() != -1) { ipw.println("-stagedSessionId: " + getStagedSessionId()); @@ -955,4 +965,17 @@ class Rollback { } ipw.decreaseIndent(); } + + @WorkerThread + String getStateDescription() { + assertInWorkerThread(); + return mStateDescription; + } + + @VisibleForTesting + void setState(@RollbackState int state, String description) { + assertInWorkerThread(); + mState = state; + mStateDescription = description; + } } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index b34d46ff1a0c..192a00303a30 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -179,7 +179,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba mInstaller = new Installer(mContext); mInstaller.onStart(); - mRollbackStore = new RollbackStore(new File(Environment.getDataDirectory(), "rollback")); + mRollbackStore = new RollbackStore( + new File(Environment.getDataDirectory(), "rollback"), + new File(Environment.getDataDirectory(), "rollback-history")); mPackageHealthObserver = new RollbackPackageHealthObserver(mContext); mAppDataRollbackHelper = new AppDataRollbackHelper(mInstaller); @@ -201,7 +203,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba } else { // Delete rollbacks when build fingerprint has changed. for (Rollback rollback : mRollbacks) { - rollback.delete(mAppDataRollbackHelper); + deleteRollback(rollback, "Fingerprint changed"); } mRollbacks.clear(); } @@ -271,7 +273,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba Rollback rollback = getRollbackForSession(sessionId); if (rollback != null && rollback.isEnabling()) { mRollbacks.remove(rollback); - rollback.delete(mAppDataRollbackHelper); + deleteRollback(rollback, "Rollback canceled"); } } } @@ -477,14 +479,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba } @WorkerThread - private void expireRollbackForPackageInternal(String packageName) { + private void expireRollbackForPackageInternal(String packageName, String reason) { assertInWorkerThread(); Iterator<Rollback> iter = mRollbacks.iterator(); while (iter.hasNext()) { Rollback rollback = iter.next(); if (rollback.includesPackage(packageName)) { iter.remove(); - rollback.delete(mAppDataRollbackHelper); + deleteRollback(rollback, reason); } } } @@ -496,7 +498,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba mContext.enforceCallingOrSelfPermission( Manifest.permission.TEST_MANAGE_ROLLBACKS, "expireRollbackForPackage"); - awaitResult(() -> expireRollbackForPackageInternal(packageName)); + awaitResult(() -> expireRollbackForPackageInternal(packageName, "Expired by API")); } @ExtThread @@ -612,7 +614,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba .getPackageInstaller().getSessionInfo(rollback.getStagedSessionId()); if (session == null || session.isStagedSessionFailed()) { iter.remove(); - rollback.delete(mAppDataRollbackHelper); + deleteRollback(rollback, + "Session " + session.getSessionId() + " not existed or failed"); continue; } @@ -666,7 +669,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba && rollback.includesPackageWithDifferentVersion(packageName, installedVersion)) { iter.remove(); - rollback.delete(mAppDataRollbackHelper); + deleteRollback(rollback, "Package " + packageName + " replaced"); } } } @@ -678,7 +681,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba @WorkerThread private void onPackageFullyRemoved(String packageName) { assertInWorkerThread(); - expireRollbackForPackageInternal(packageName); + expireRollbackForPackageInternal(packageName, "Package " + packageName + " removed"); } /** @@ -713,14 +716,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba Iterator<Rollback> iter = mRollbacks.iterator(); while (iter.hasNext()) { Rollback rollback = iter.next(); - if (!rollback.isAvailable()) { + if (!rollback.isAvailable() && !rollback.isCommitted()) { continue; } Instant rollbackTimestamp = rollback.getTimestamp(); if (!now.isBefore(rollbackTimestamp.plusMillis(mRollbackLifetimeDurationInMillis))) { Slog.i(TAG, "runExpiration id=" + rollback.info.getRollbackId()); iter.remove(); - rollback.delete(mAppDataRollbackHelper); + deleteRollback(rollback, "Expired by timeout"); } else if (oldest == null || oldest.isAfter(rollbackTimestamp)) { oldest = rollbackTimestamp; } @@ -1132,7 +1135,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba Slog.w(TAG, "Delete rollback id=" + rollback.info.getRollbackId() + " for failed session id=" + sessionId); mRollbacks.remove(rollback); - rollback.delete(mAppDataRollbackHelper); + deleteRollback(rollback, "Session " + sessionId + " failed"); } } } @@ -1159,7 +1162,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba if (!rollback.allPackagesEnabled()) { Slog.e(TAG, "Failed to enable rollback for all packages in session."); mRollbacks.remove(rollback); - rollback.delete(mAppDataRollbackHelper); + deleteRollback(rollback, "Failed to enable rollback for all packages in session"); return false; } @@ -1240,6 +1243,18 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba rollback.dump(ipw); } ipw.println(); + + List<Rollback> historicalRollbacks = mRollbackStore.loadHistorialRollbacks(); + if (!historicalRollbacks.isEmpty()) { + ipw.println("Historical rollbacks:"); + ipw.increaseIndent(); + for (Rollback rollback : historicalRollbacks) { + rollback.dump(ipw); + } + ipw.decreaseIndent(); + ipw.println(); + } + PackageWatchdog.getInstance(mContext).dump(ipw); }); } @@ -1329,4 +1344,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba } return null; } + + @WorkerThread + private void deleteRollback(Rollback rollback, String reason) { + assertInWorkerThread(); + rollback.delete(mAppDataRollbackHelper, reason); + mRollbackStore.saveRollbackToHistory(rollback); + } } diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java index 2ee87e67e467..35c9f9ae6683 100644 --- a/services/core/java/com/android/server/rollback/RollbackStore.java +++ b/services/core/java/com/android/server/rollback/RollbackStore.java @@ -69,18 +69,20 @@ class RollbackStore { // * XXX, YYY are the rollbackIds for the corresponding rollbacks. // * rollback.json contains all relevant metadata for the rollback. private final File mRollbackDataDir; + private final File mRollbackHistoryDir; - RollbackStore(File rollbackDataDir) { + RollbackStore(File rollbackDataDir, File rollbackHistoryDir) { mRollbackDataDir = rollbackDataDir; + mRollbackHistoryDir = rollbackHistoryDir; } /** * Reads the rollbacks from persistent storage. */ - List<Rollback> loadRollbacks() { + private static List<Rollback> loadRollbacks(File rollbackDataDir) { List<Rollback> rollbacks = new ArrayList<>(); - mRollbackDataDir.mkdirs(); - for (File rollbackDir : mRollbackDataDir.listFiles()) { + rollbackDataDir.mkdirs(); + for (File rollbackDir : rollbackDataDir.listFiles()) { if (rollbackDir.isDirectory()) { try { rollbacks.add(loadRollback(rollbackDir)); @@ -93,6 +95,14 @@ class RollbackStore { return rollbacks; } + List<Rollback> loadRollbacks() { + return loadRollbacks(mRollbackDataDir); + } + + List<Rollback> loadHistorialRollbacks() { + return loadRollbacks(mRollbackHistoryDir); + } + /** * Converts a {@code JSONArray} of integers to a {@code List<Integer>}. */ @@ -258,15 +268,17 @@ class RollbackStore { /** * Saves the given rollback to persistent storage. */ - static void saveRollback(Rollback rollback) { + private static void saveRollback(Rollback rollback, File backDir) { FileOutputStream fos = null; - AtomicFile file = new AtomicFile(new File(rollback.getBackupDir(), "rollback.json")); + AtomicFile file = new AtomicFile(new File(backDir, "rollback.json")); try { + backDir.mkdirs(); JSONObject dataJson = new JSONObject(); dataJson.put("info", rollbackInfoToJson(rollback.info)); dataJson.put("timestamp", rollback.getTimestamp().toString()); dataJson.put("stagedSessionId", rollback.getStagedSessionId()); dataJson.put("state", rollback.getStateAsString()); + dataJson.put("stateDescription", rollback.getStateDescription()); dataJson.put("restoreUserDataInProgress", rollback.isRestoreUserDataInProgress()); dataJson.put("userId", rollback.getUserId()); dataJson.putOpt("installerPackageName", rollback.getInstallerPackageName()); @@ -286,6 +298,22 @@ class RollbackStore { } } + static void saveRollback(Rollback rollback) { + saveRollback(rollback, rollback.getBackupDir()); + } + + /** + * Saves the rollback to $mRollbackHistoryDir/ROLLBACKID-HEX for debugging purpose. + */ + void saveRollbackToHistory(Rollback rollback) { + // The same id might be allocated to different historical rollbacks. + // Let's add a suffix to avoid naming collision. + String suffix = Long.toHexString(rollback.getTimestamp().getEpochSecond()); + String dirName = Integer.toString(rollback.info.getRollbackId()); + File backupDir = new File(mRollbackHistoryDir, dirName + "-" + suffix); + saveRollback(rollback, backupDir); + } + /** * Removes all persistent storage associated with the given rollback. */ @@ -318,6 +346,7 @@ class RollbackStore { Instant.parse(dataJson.getString("timestamp")), dataJson.getInt("stagedSessionId"), rollbackStateFromString(dataJson.getString("state")), + dataJson.optString("stateDescription"), dataJson.getBoolean("restoreUserDataInProgress"), dataJson.optInt("userId", UserHandle.SYSTEM.getIdentifier()), dataJson.optString("installerPackageName", ""), diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java index 789dd5273094..7de0e87f91c3 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java @@ -132,7 +132,7 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub { /** Internal method for handling the auto time setting being changed. */ @VisibleForTesting public void handleAutoTimeDetectionChanged() { - mHandler.post(mTimeDetectorStrategy::handleAutoTimeDetectionChanged); + mHandler.post(mTimeDetectorStrategy::handleAutoTimeConfigChanged); } @Override diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java index 3b2b992c15ba..f278ef68c536 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java @@ -16,6 +16,7 @@ package com.android.server.timedetector; +import android.annotation.IntDef; import android.annotation.NonNull; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; @@ -25,6 +26,9 @@ import android.util.IndentingPrintWriter; import com.android.server.timezonedetector.Dumpable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * The interface for the class that implements the time detection algorithm used by the * {@link TimeDetectorService}. @@ -37,22 +41,41 @@ import com.android.server.timezonedetector.Dumpable; */ public interface TimeDetectorStrategy extends Dumpable { - /** Process the suggested time from telephony sources. */ + @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK }) + @Retention(RetentionPolicy.SOURCE) + @interface Origin {} + + /** Used when a time value originated from a telephony signal. */ + @Origin + int ORIGIN_TELEPHONY = 1; + + /** Used when a time value originated from a user / manual settings. */ + @Origin + int ORIGIN_MANUAL = 2; + + /** Used when a time value originated from a network signal. */ + @Origin + int ORIGIN_NETWORK = 3; + + /** Processes the suggested time from telephony sources. */ void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion); /** - * Process the suggested manually entered time. Returns {@code false} if the suggestion was + * Processes the suggested manually entered time. Returns {@code false} if the suggestion was * invalid, or the device configuration prevented the suggestion being used, {@code true} if the * suggestion was accepted. A suggestion that is valid but does not change the time because it * matches the current device time is considered accepted. */ boolean suggestManualTime(@NonNull ManualTimeSuggestion timeSuggestion); - /** Process the suggested time from network sources. */ + /** Processes the suggested time from network sources. */ void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion); - /** Handle the auto-time setting being toggled on or off. */ - void handleAutoTimeDetectionChanged(); + /** + * Handles the auto-time configuration changing For example, when the auto-time setting is + * toggled on or off. + */ + void handleAutoTimeConfigChanged(); // Utility methods below are to be moved to a better home when one becomes more obvious. @@ -64,4 +87,38 @@ public interface TimeDetectorStrategy extends Dumpable { return (referenceClockMillisNow - timeValue.getReferenceTimeMillis()) + timeValue.getValue(); } + + /** + * Converts one of the {@code ORIGIN_} constants to a human readable string suitable for config + * and debug usage. Throws an {@link IllegalArgumentException} if the value is unrecognized. + */ + static String originToString(@Origin int origin) { + switch (origin) { + case ORIGIN_MANUAL: + return "manual"; + case ORIGIN_NETWORK: + return "network"; + case ORIGIN_TELEPHONY: + return "telephony"; + default: + throw new IllegalArgumentException("origin=" + origin); + } + } + + /** + * Converts a human readable config string to one of the {@code ORIGIN_} constants. + * Throws an {@link IllegalArgumentException} if the value is unrecognized. + */ + static @Origin int stringToOrigin(String originString) { + switch (originString) { + case "manual": + return ORIGIN_MANUAL; + case "network": + return ORIGIN_NETWORK; + case "telephony": + return ORIGIN_TELEPHONY; + default: + throw new IllegalArgumentException("originString=" + originString); + } + } } diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java index e06fe9276323..5b6de0518999 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java @@ -16,16 +16,21 @@ package com.android.server.timedetector; +import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin; + import android.annotation.NonNull; import android.app.AlarmManager; import android.content.ContentResolver; import android.content.Context; +import android.os.Build; +import android.os.Environment; import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; import android.util.Slog; +import java.time.Instant; import java.util.Objects; /** @@ -38,6 +43,13 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat private static final int SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT = 2 * 1000; /** + * Time in the past. If automatic time suggestion is before this point, it's + * incorrect for sure. + */ + private static final Instant TIME_LOWER_BOUND = Instant.ofEpochMilli( + Long.max(Environment.getRootDirectory().lastModified(), Build.TIME)); + + /** * If a newly calculated system clock time and the current system clock time differs by this or * more the system clock will actually be updated. Used to prevent the system clock being set * for only minor differences. @@ -48,6 +60,7 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat @NonNull private final ContentResolver mContentResolver; @NonNull private final PowerManager.WakeLock mWakeLock; @NonNull private final AlarmManager mAlarmManager; + @NonNull private final int[] mOriginPriorities; public TimeDetectorStrategyCallbackImpl(@NonNull Context context) { mContext = Objects.requireNonNull(context); @@ -62,6 +75,15 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat mSystemClockUpdateThresholdMillis = SystemProperties.getInt("ro.sys.time_detector_update_diff", SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT); + + // TODO(b/172230856): Obtain these values from configuration. + String[] originStrings = { "telephony", "network" }; + int[] origins = new int[originStrings.length]; + for (int i = 0; i < originStrings.length; i++) { + int origin = stringToOrigin(originStrings[i]); + origins[i] = origin; + } + mOriginPriorities = origins; } @Override @@ -79,6 +101,16 @@ public final class TimeDetectorStrategyCallbackImpl implements TimeDetectorStrat } @Override + public Instant autoTimeLowerBound() { + return TIME_LOWER_BOUND; + } + + @Override + public int[] getAutoOriginPriorities() { + return mOriginPriorities; + } + + @Override public void acquireWakeLock() { if (mWakeLock.isHeld()) { Slog.wtf(TAG, "WakeLock " + mWakeLock + " already held"); diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java index 7a2680bbe349..d8cada55781c 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java @@ -16,7 +16,8 @@ package com.android.server.timedetector; -import android.annotation.IntDef; +import static com.android.server.timedetector.TimeDetectorStrategy.originToString; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AlarmManager; @@ -33,8 +34,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.timezonedetector.ArrayMapWithHistory; import com.android.server.timezonedetector.ReferenceWithHistory; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; +import java.time.Instant; +import java.util.Arrays; /** * An implementation of {@link TimeDetectorStrategy} that passes telephony and manual suggestions to @@ -62,22 +63,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { static final long MAX_UTC_TIME_AGE_MILLIS = TELEPHONY_BUCKET_COUNT * TELEPHONY_BUCKET_SIZE_MILLIS; - @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK }) - @Retention(RetentionPolicy.SOURCE) - public @interface Origin {} - - /** Used when a time value originated from a telephony signal. */ - @Origin - private static final int ORIGIN_TELEPHONY = 1; - - /** Used when a time value originated from a user / manual settings. */ - @Origin - private static final int ORIGIN_MANUAL = 2; - - /** Used when a time value originated from a network signal. */ - @Origin - private static final int ORIGIN_NETWORK = 3; - /** * CLOCK_PARANOIA: The maximum difference allowed between the expected system clock time and the * actual system clock time before a warning is logged. Used to help identify situations where @@ -142,6 +127,21 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { /** Returns true if automatic time detection is enabled. */ boolean isAutoTimeDetectionEnabled(); + /** + * Returns a lower bound for valid automatic times. It is guaranteed to be in the past, + * i.e. it is unrelated to the current system clock time. + * It holds no other meaning; it could be related to when the device system image was built, + * or could be updated by a mainline module. + */ + @NonNull + Instant autoTimeLowerBound(); + + /** + * Returns the order to look at time suggestions when automatically detecting time. + * See {@code #ORIGIN_} constants + */ + @Origin int[] getAutoOriginPriorities(); + /** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */ void acquireWakeLock(); @@ -176,7 +176,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { @Override public synchronized void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion) { - if (!validateSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) { + if (!validateAutoSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) { return; } @@ -210,9 +210,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { return; } - // Perform validation / input filtering and record the validated suggestion against the - // slotIndex. - if (!validateAndStoreTelephonySuggestion(timeSuggestion)) { + if (!validateAutoSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) { + return; + } + + // Perform input filtering and record the validated suggestion against the slotIndex. + if (!storeTelephonySuggestion(timeSuggestion)) { return; } @@ -223,12 +226,12 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { } @Override - public synchronized void handleAutoTimeDetectionChanged() { + public synchronized void handleAutoTimeConfigChanged() { boolean enabled = mCallback.isAutoTimeDetectionEnabled(); // When automatic time detection is enabled we update the system clock instantly if we can. // Conversely, when automatic time detection is disabled we leave the clock as it is. if (enabled) { - String reason = "Auto time zone detection setting enabled."; + String reason = "Auto time zone detection config changed."; doAutoTimeDetection(reason); } else { // CLOCK_PARANOIA: We are losing "control" of the system clock so we cannot predict what @@ -269,14 +272,9 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { } @GuardedBy("this") - private boolean validateAndStoreTelephonySuggestion( + private boolean storeTelephonySuggestion( @NonNull TelephonyTimeSuggestion suggestion) { TimestampedValue<Long> newUtcTime = suggestion.getUtcTime(); - if (!validateSuggestionTime(newUtcTime, suggestion)) { - // There's probably nothing useful we can do: elsewhere we assume that reference - // times are in the past so just stop here. - return false; - } int slotIndex = suggestion.getSlotIndex(); TelephonyTimeSuggestion previousSuggestion = mSuggestionBySlotIndex.get(slotIndex); @@ -327,6 +325,26 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { return true; } + private boolean validateAutoSuggestionTime( + @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) { + return validateSuggestionTime(newUtcTime, suggestion) + && validateSuggestionAgainstLowerBound(newUtcTime, suggestion); + } + + private boolean validateSuggestionAgainstLowerBound( + @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) { + Instant lowerBound = mCallback.autoTimeLowerBound(); + + // Suggestion is definitely wrong if it comes before lower time bound. + if (lowerBound.isAfter(Instant.ofEpochMilli(newUtcTime.getValue()))) { + Slog.w(LOG_TAG, "Suggestion points to time before lower bound, skipping it. " + + "suggestion=" + suggestion + ", lower bound=" + lowerBound); + return false; + } + + return true; + } + @GuardedBy("this") private void doAutoTimeDetection(@NonNull String detectionReason) { if (!mCallback.isAutoTimeDetectionEnabled()) { @@ -334,33 +352,44 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { return; } - // Android devices currently prioritize any telephony over network signals. There are - // carrier compliance tests that would need to be changed before we could ignore NITZ or - // prefer NTP generally. This check is cheap on devices without telephony hardware. - TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion(); - if (bestTelephonySuggestion != null) { - final TimestampedValue<Long> newUtcTime = bestTelephonySuggestion.getUtcTime(); - String cause = "Found good telephony suggestion." - + ", bestTelephonySuggestion=" + bestTelephonySuggestion - + ", detectionReason=" + detectionReason; - setSystemClockIfRequired(ORIGIN_TELEPHONY, newUtcTime, cause); - return; - } + // Try the different origins one at a time. + int[] originPriorities = mCallback.getAutoOriginPriorities(); + for (int origin : originPriorities) { + TimestampedValue<Long> newUtcTime = null; + String cause = null; + if (origin == ORIGIN_TELEPHONY) { + TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion(); + if (bestTelephonySuggestion != null) { + newUtcTime = bestTelephonySuggestion.getUtcTime(); + cause = "Found good telephony suggestion." + + ", bestTelephonySuggestion=" + bestTelephonySuggestion + + ", detectionReason=" + detectionReason; + } + } else if (origin == ORIGIN_NETWORK) { + NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion(); + if (networkSuggestion != null) { + newUtcTime = networkSuggestion.getUtcTime(); + cause = "Found good network suggestion." + + ", networkSuggestion=" + networkSuggestion + + ", detectionReason=" + detectionReason; + } + } else { + Slog.w(LOG_TAG, "Unknown or unsupported origin=" + origin + + " in " + Arrays.toString(originPriorities) + + ": Skipping"); + } - // There is no good telephony suggestion, try network. - NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion(); - if (networkSuggestion != null) { - final TimestampedValue<Long> newUtcTime = networkSuggestion.getUtcTime(); - String cause = "Found good network suggestion." - + ", networkSuggestion=" + networkSuggestion - + ", detectionReason=" + detectionReason; - setSystemClockIfRequired(ORIGIN_NETWORK, newUtcTime, cause); - return; + // Update the system clock if a good suggestion has been found. + if (newUtcTime != null) { + setSystemClockIfRequired(origin, newUtcTime, cause); + return; + } } if (DBG) { - Slog.d(LOG_TAG, "Could not determine time: No best telephony or network suggestion." - + " detectionReason=" + detectionReason); + Slog.d(LOG_TAG, "Could not determine time: No suggestion found in" + + " originPriorities=" + Arrays.toString(originPriorities) + + ", detectionReason=" + detectionReason); } } @@ -445,7 +474,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { // Validate first. TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime(); if (!validateSuggestionUtcTime(elapsedRealtimeMillis, utcTime)) { - Slog.w(LOG_TAG, "Existing suggestion found to be invalid " + Slog.w(LOG_TAG, "Existing suggestion found to be invalid" + " elapsedRealtimeMillis=" + elapsedRealtimeMillis + ", timeSuggestion=" + timeSuggestion); return TELEPHONY_INVALID_SCORE; @@ -494,7 +523,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { if (!mCallback.isAutoTimeDetectionEnabled()) { if (DBG) { Slog.d(LOG_TAG, "Auto time detection is not enabled." - + " origin=" + origin + + " origin=" + originToString(origin) + ", time=" + time + ", cause=" + cause); } @@ -504,7 +533,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { if (mCallback.isAutoTimeDetectionEnabled()) { if (DBG) { Slog.d(LOG_TAG, "Auto time detection is enabled." - + " origin=" + origin + + " origin=" + originToString(origin) + ", time=" + time + ", cause=" + cause); } @@ -526,7 +555,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { @GuardedBy("this") private boolean setSystemClockUnderWakeLock( - int origin, @NonNull TimestampedValue<Long> newTime, @NonNull Object cause) { + @Origin int origin, @NonNull TimestampedValue<Long> newTime, @NonNull String cause) { long elapsedRealtimeMillis = mCallback.elapsedRealtimeMillis(); boolean isOriginAutomatic = isOriginAutomatic(origin); diff --git a/services/core/java/com/android/server/uri/TEST_MAPPING b/services/core/java/com/android/server/uri/TEST_MAPPING index e5cda03be25d..a9525f4a82ad 100644 --- a/services/core/java/com/android/server/uri/TEST_MAPPING +++ b/services/core/java/com/android/server/uri/TEST_MAPPING @@ -7,6 +7,26 @@ "include-filter": "com.android.server.uri." } ] + }, + { + "name": "CtsAppSecurityHostTestCases", + "options": [ + { + "include-filter": "android.appsecurity.cts.ExternalStorageHostTest#testGrantUriPermission" + }, + { + "include-filter": "android.appsecurity.cts.ExternalStorageHostTest#testGrantUriPermission29" + }, + { + "include-filter": "android.appsecurity.cts.ExternalStorageHostTest#testMediaNone" + }, + { + "include-filter": "android.appsecurity.cts.ExternalStorageHostTest#testMediaNone28" + }, + { + "include-filter": "android.appsecurity.cts.ExternalStorageHostTest#testMediaNone29" + } + ] } ], "postsubmit": [ diff --git a/services/core/java/com/android/server/vibrator/InputDeviceDelegate.java b/services/core/java/com/android/server/vibrator/InputDeviceDelegate.java new file mode 100644 index 000000000000..edbc05802697 --- /dev/null +++ b/services/core/java/com/android/server/vibrator/InputDeviceDelegate.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vibrator; + +import android.content.Context; +import android.hardware.input.InputManager; +import android.os.Handler; +import android.os.VibrationAttributes; +import android.os.VibrationEffect; +import android.os.Vibrator; +import android.util.SparseArray; +import android.view.InputDevice; + +import com.android.internal.annotations.GuardedBy; + +/** Delegates vibrations to all connected {@link InputDevice} with available {@link Vibrator}. */ +// TODO(b/159207608): Make this package-private once vibrator services are moved to this package +public final class InputDeviceDelegate implements InputManager.InputDeviceListener { + private static final String TAG = "InputDeviceDelegate"; + + private final Object mLock = new Object(); + private final Handler mHandler; + private final InputManager mInputManager; + + @GuardedBy("mLock") + private final SparseArray<Vibrator> mInputDeviceVibrators = new SparseArray<>(); + + /** + * Flag updated via {@link #updateInputDeviceVibrators(boolean)}, holding the value of {@link + * android.provider.Settings.System#VIBRATE_INPUT_DEVICES}. + */ + @GuardedBy("mLock") + private boolean mShouldVibrateInputDevices; + + public InputDeviceDelegate(Context context, Handler handler) { + mHandler = handler; + mInputManager = context.getSystemService(InputManager.class); + } + + @Override + public void onInputDeviceAdded(int deviceId) { + updateInputDevice(deviceId); + } + + @Override + public void onInputDeviceChanged(int deviceId) { + updateInputDevice(deviceId); + } + + @Override + public void onInputDeviceRemoved(int deviceId) { + synchronized (mLock) { + mInputDeviceVibrators.remove(deviceId); + } + } + + /** + * Return {@code true} is there are input devices with vibrators available and vibrations should + * be delegated to them. + */ + public boolean isAvailable() { + synchronized (mLock) { + // mInputDeviceVibrators is cleared when settings are disabled, so this check is enough. + return mInputDeviceVibrators.size() > 0; + } + } + + /** + * Vibrate all {@link InputDevice} with {@link Vibrator} available using given effect. + * + * @return {@link #isAvailable()} + */ + public boolean vibrateIfAvailable(int uid, String opPkg, VibrationEffect effect, + String reason, VibrationAttributes attrs) { + synchronized (mLock) { + for (int i = 0; i < mInputDeviceVibrators.size(); i++) { + mInputDeviceVibrators.valueAt(i).vibrate(uid, opPkg, effect, reason, attrs); + } + return mInputDeviceVibrators.size() > 0; + } + } + + /** + * Cancel vibration on all {@link InputDevice} with {@link Vibrator} available. + * + * @return {@link #isAvailable()} + */ + public boolean cancelVibrateIfAvailable() { + synchronized (mLock) { + for (int i = 0; i < mInputDeviceVibrators.size(); i++) { + mInputDeviceVibrators.valueAt(i).cancel(); + } + return mInputDeviceVibrators.size() > 0; + } + } + + /** + * Updates the list of {@link InputDevice} vibrators based on the {@link + * VibrationSettings#shouldVibrateInputDevices()} setting current value and the + * devices currently available in {@link InputManager#getInputDeviceIds()}. + * + * @return true if there was any change in input devices available or related settings. + */ + public boolean updateInputDeviceVibrators(boolean vibrateInputDevices) { + synchronized (mLock) { + if (vibrateInputDevices == mShouldVibrateInputDevices) { + // No need to update if settings haven't changed. + return false; + } + + mShouldVibrateInputDevices = vibrateInputDevices; + mInputDeviceVibrators.clear(); + + if (vibrateInputDevices) { + // Register the listener first so any device added/updated/removed after the call to + // getInputDeviceIds() will trigger the callbacks (which will wait on the lock for + // this loop to finish). + mInputManager.registerInputDeviceListener(this, mHandler); + + for (int deviceId : mInputManager.getInputDeviceIds()) { + InputDevice device = mInputManager.getInputDevice(deviceId); + if (device == null) { + continue; + } + Vibrator vibrator = device.getVibrator(); + if (vibrator.hasVibrator()) { + mInputDeviceVibrators.put(device.getId(), vibrator); + } + } + } else { + mInputManager.unregisterInputDeviceListener(this); + } + } + + return true; + } + + private void updateInputDevice(int deviceId) { + synchronized (mLock) { + if (!mShouldVibrateInputDevices) { + // No need to keep this device vibrator if setting is off. + return; + } + InputDevice device = mInputManager.getInputDevice(deviceId); + if (device == null) { + mInputDeviceVibrators.remove(deviceId); + return; + } + Vibrator vibrator = device.getVibrator(); + if (vibrator.hasVibrator()) { + mInputDeviceVibrators.put(deviceId, vibrator); + } else { + mInputDeviceVibrators.remove(deviceId); + } + } + } +} diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java new file mode 100644 index 000000000000..e2cdd02deab9 --- /dev/null +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vibrator; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.IBinder; +import android.os.SystemClock; +import android.os.VibrationAttributes; +import android.os.VibrationEffect; +import android.util.proto.ProtoOutputStream; + +import com.android.server.ComposedProto; +import com.android.server.OneShotProto; +import com.android.server.PrebakedProto; +import com.android.server.VibrationAttributesProto; +import com.android.server.VibrationEffectProto; +import com.android.server.VibrationProto; +import com.android.server.WaveformProto; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** Represents a vibration request to the vibrator service. */ +// TODO(b/159207608): Make this package-private once vibrator services are moved to this package +public class Vibration { + private static final String TAG = "Vibration"; + private static final SimpleDateFormat DEBUG_DATE_FORMAT = + new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); + + public enum Status { + RUNNING, + FINISHED, + FORWARDED_TO_INPUT_DEVICES, + CANCELLED, + ERROR_APP_OPS, + IGNORED, + IGNORED_APP_OPS, + IGNORED_BACKGROUND, + IGNORED_RINGTONE, + IGNORED_UNKNOWN_VIBRATION, + IGNORED_UNSUPPORTED, + IGNORED_FOR_ALARM, + IGNORED_FOR_EXTERNAL, + IGNORED_FOR_ONGOING, + IGNORED_FOR_POWER, + IGNORED_FOR_SETTINGS, + } + + /** Start time in CLOCK_BOOTTIME base. */ + public final long startTime; + public final VibrationAttributes attrs; + public final long id; + public final int uid; + public final String opPkg; + public final String reason; + public final IBinder token; + + /** The actual effect to be played. */ + @Nullable + private VibrationEffect mEffect; + + /** + * The original effect that was requested. Typically these two things differ because the effect + * was scaled based on the users vibration intensity settings. + */ + @Nullable + private VibrationEffect mOriginalEffect; + + /** + * Start/end times in unix epoch time. Only to be used for debugging purposes and to correlate + * with other system events, any duration calculations should be done use {@link #startTime} so + * as not to be affected by discontinuities created by RTC adjustments. + */ + private final long mStartTimeDebug; + private long mEndTimeDebug; + private Status mStatus; + + public Vibration(IBinder token, int id, VibrationEffect effect, + VibrationAttributes attrs, int uid, String opPkg, String reason) { + this.token = token; + this.mEffect = effect; + this.id = id; + this.startTime = SystemClock.elapsedRealtime(); + this.attrs = attrs; + this.uid = uid; + this.opPkg = opPkg; + this.reason = reason; + mStartTimeDebug = System.currentTimeMillis(); + mStatus = Status.RUNNING; + } + + /** + * Set the {@link Status} of this vibration and the current system time as this + * vibration end time, for debugging purposes. + * + * <p>This method will only accept given value if the current status is {@link + * Status#RUNNING}. + */ + public void end(Status status) { + if (hasEnded()) { + // Vibration already ended, keep first ending status set and ignore this one. + return; + } + mStatus = status; + mEndTimeDebug = System.currentTimeMillis(); + } + + /** + * Replace this vibration effect if given {@code scaledEffect} is different, preserving the + * original one for debug purposes. + */ + public void updateEffect(@NonNull VibrationEffect newEffect) { + if (newEffect.equals(mEffect)) { + return; + } + mOriginalEffect = mEffect; + mEffect = newEffect; + } + + /** Return true is current status is different from {@link Status#RUNNING}. */ + public boolean hasEnded() { + return mStatus != Status.RUNNING; + } + + /** Return the effect that should be played by this vibration. */ + @Nullable + public VibrationEffect getEffect() { + return mEffect; + } + + /** Return {@link Vibration.DebugInfo} with read-only debug information about this vibration. */ + public Vibration.DebugInfo getDebugInfo() { + return new Vibration.DebugInfo( + mStartTimeDebug, mEndTimeDebug, mEffect, mOriginalEffect, /* scale= */ 0, attrs, + uid, opPkg, reason, mStatus); + } + + /** Debug information about vibrations. */ + public static final class DebugInfo { + private final long mStartTimeDebug; + private final long mEndTimeDebug; + private final VibrationEffect mEffect; + private final VibrationEffect mOriginalEffect; + private final float mScale; + private final VibrationAttributes mAttrs; + private final int mUid; + private final String mOpPkg; + private final String mReason; + private final Status mStatus; + + public DebugInfo(long startTimeDebug, long endTimeDebug, VibrationEffect effect, + VibrationEffect originalEffect, float scale, VibrationAttributes attrs, + int uid, String opPkg, String reason, Status status) { + mStartTimeDebug = startTimeDebug; + mEndTimeDebug = endTimeDebug; + mEffect = effect; + mOriginalEffect = originalEffect; + mScale = scale; + mAttrs = attrs; + mUid = uid; + mOpPkg = opPkg; + mReason = reason; + mStatus = status; + } + + @Override + public String toString() { + return new StringBuilder() + .append("startTime: ") + .append(DEBUG_DATE_FORMAT.format(new Date(mStartTimeDebug))) + .append(", endTime: ") + .append(mEndTimeDebug == 0 ? null + : DEBUG_DATE_FORMAT.format(new Date(mEndTimeDebug))) + .append(", status: ") + .append(mStatus.name().toLowerCase()) + .append(", effect: ") + .append(mEffect) + .append(", originalEffect: ") + .append(mOriginalEffect) + .append(", scale: ") + .append(String.format("%.2f", mScale)) + .append(", attrs: ") + .append(mAttrs) + .append(", uid: ") + .append(mUid) + .append(", opPkg: ") + .append(mOpPkg) + .append(", reason: ") + .append(mReason) + .toString(); + } + + /** Write this info into given {@code fieldId} on {@link ProtoOutputStream}. */ + public void dumpProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(VibrationProto.START_TIME, mStartTimeDebug); + proto.write(VibrationProto.END_TIME, mEndTimeDebug); + proto.write(VibrationProto.STATUS, mStatus.ordinal()); + + final long attrsToken = proto.start(VibrationProto.ATTRIBUTES); + proto.write(VibrationAttributesProto.USAGE, mAttrs.getUsage()); + proto.write(VibrationAttributesProto.AUDIO_USAGE, mAttrs.getAudioUsage()); + proto.write(VibrationAttributesProto.FLAGS, mAttrs.getFlags()); + proto.end(attrsToken); + + if (mEffect != null) { + dumpEffect(proto, VibrationProto.EFFECT, mEffect); + } + if (mOriginalEffect != null) { + dumpEffect(proto, VibrationProto.ORIGINAL_EFFECT, mOriginalEffect); + } + + proto.end(token); + } + + private void dumpEffect(ProtoOutputStream proto, long fieldId, VibrationEffect effect) { + final long token = proto.start(fieldId); + if (effect instanceof VibrationEffect.OneShot) { + dumpEffect(proto, VibrationEffectProto.ONESHOT, (VibrationEffect.OneShot) effect); + } else if (effect instanceof VibrationEffect.Waveform) { + dumpEffect(proto, VibrationEffectProto.WAVEFORM, (VibrationEffect.Waveform) effect); + } else if (effect instanceof VibrationEffect.Prebaked) { + dumpEffect(proto, VibrationEffectProto.PREBAKED, (VibrationEffect.Prebaked) effect); + } else if (effect instanceof VibrationEffect.Composed) { + dumpEffect(proto, VibrationEffectProto.COMPOSED, (VibrationEffect.Composed) effect); + } + proto.end(token); + } + + private void dumpEffect(ProtoOutputStream proto, long fieldId, + VibrationEffect.OneShot effect) { + final long token = proto.start(fieldId); + proto.write(OneShotProto.DURATION, (int) effect.getDuration()); + proto.write(OneShotProto.AMPLITUDE, effect.getAmplitude()); + proto.end(token); + } + + private void dumpEffect(ProtoOutputStream proto, long fieldId, + VibrationEffect.Waveform effect) { + final long token = proto.start(fieldId); + for (long timing : effect.getTimings()) { + proto.write(WaveformProto.TIMINGS, (int) timing); + } + for (int amplitude : effect.getAmplitudes()) { + proto.write(WaveformProto.AMPLITUDES, amplitude); + } + proto.write(WaveformProto.REPEAT, effect.getRepeatIndex() >= 0); + proto.end(token); + } + + private void dumpEffect(ProtoOutputStream proto, long fieldId, + VibrationEffect.Prebaked effect) { + final long token = proto.start(fieldId); + proto.write(PrebakedProto.EFFECT_ID, effect.getId()); + proto.write(PrebakedProto.EFFECT_STRENGTH, effect.getEffectStrength()); + proto.write(PrebakedProto.FALLBACK, effect.shouldFallback()); + proto.end(token); + } + + private void dumpEffect(ProtoOutputStream proto, long fieldId, + VibrationEffect.Composed effect) { + final long token = proto.start(fieldId); + for (VibrationEffect.Composition.PrimitiveEffect primitive : + effect.getPrimitiveEffects()) { + proto.write(ComposedProto.EFFECT_IDS, primitive.id); + proto.write(ComposedProto.EFFECT_SCALES, primitive.scale); + proto.write(ComposedProto.DELAYS, primitive.delay); + } + proto.end(token); + } + } +} diff --git a/services/core/java/com/android/server/vibrator/VibrationScaler.java b/services/core/java/com/android/server/vibrator/VibrationScaler.java index 42a0a706a1c7..5f7e47d6ca29 100644 --- a/services/core/java/com/android/server/vibrator/VibrationScaler.java +++ b/services/core/java/com/android/server/vibrator/VibrationScaler.java @@ -31,7 +31,6 @@ public final class VibrationScaler { // Scale levels. Each level, except MUTE, is defined as the delta between the current setting // and the default intensity for that type of vibration (i.e. current - default). - private static final int SCALE_MUTE = IExternalVibratorService.SCALE_MUTE; // -100 private static final int SCALE_VERY_LOW = IExternalVibratorService.SCALE_VERY_LOW; // -2 private static final int SCALE_LOW = IExternalVibratorService.SCALE_LOW; // -1 private static final int SCALE_NONE = IExternalVibratorService.SCALE_NONE; // 0 diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java index 06a1f599f491..6a5d1c4173c9 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSettings.java +++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java @@ -17,14 +17,17 @@ package com.android.server.vibrator; import android.content.Context; +import android.content.res.Resources; import android.database.ContentObserver; import android.media.AudioManager; import android.net.Uri; import android.os.Handler; import android.os.UserHandle; import android.os.VibrationAttributes; +import android.os.VibrationEffect; import android.os.Vibrator; import android.provider.Settings; +import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -37,6 +40,8 @@ import java.util.List; public final class VibrationSettings { private static final String TAG = "VibrationSettings"; + private static final long[] DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS = {0, 30, 100, 30}; + /** Listener for changes on vibration settings. */ public interface OnVibratorSettingsChanged { /** Callback triggered when any of the vibrator settings change. */ @@ -51,6 +56,7 @@ public final class VibrationSettings { @GuardedBy("mLock") private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>(); + private final SparseArray<VibrationEffect> mFallbackEffects; @GuardedBy("mLock") private boolean mVibrateInputDevices; @@ -84,6 +90,23 @@ public final class VibrationSettings { registerSettingsObserver( Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY)); + VibrationEffect clickEffect = createEffectFromResource( + com.android.internal.R.array.config_virtualKeyVibePattern); + VibrationEffect doubleClickEffect = VibrationEffect.createWaveform( + DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS, -1 /*repeatIndex*/); + VibrationEffect heavyClickEffect = createEffectFromResource( + com.android.internal.R.array.config_longPressVibePattern); + VibrationEffect tickEffect = createEffectFromResource( + com.android.internal.R.array.config_clockTickVibePattern); + + mFallbackEffects = new SparseArray<>(); + mFallbackEffects.put(VibrationEffect.EFFECT_CLICK, clickEffect); + mFallbackEffects.put(VibrationEffect.EFFECT_DOUBLE_CLICK, doubleClickEffect); + mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect); + mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, heavyClickEffect); + mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK, + VibrationEffect.get(VibrationEffect.EFFECT_TICK, false)); + // Update with current values from settings. updateSettings(); } @@ -150,6 +173,17 @@ public final class VibrationSettings { } /** + * Return a {@link VibrationEffect} that should be played if the device do not support given + * {@code effectId}. + * + * @param effectId one of VibrationEffect.EFFECT_* + * @return The effect to be played as a fallback + */ + public VibrationEffect getFallbackEffect(int effectId) { + return mFallbackEffects.get(effectId); + } + + /** * Return {@code true} if the device should vibrate for ringtones. * * <p>This checks the current {@link AudioManager#getRingerModeInternal()} against user settings @@ -270,6 +304,33 @@ public final class VibrationSettings { UserHandle.USER_ALL); } + private VibrationEffect createEffectFromResource(int resId) { + long[] timings = getLongIntArray(mContext.getResources(), resId); + return createEffectFromTimings(timings); + } + + private static VibrationEffect createEffectFromTimings(long[] timings) { + if (timings == null || timings.length == 0) { + return null; + } else if (timings.length == 1) { + return VibrationEffect.createOneShot(timings[0], VibrationEffect.DEFAULT_AMPLITUDE); + } else { + return VibrationEffect.createWaveform(timings, -1); + } + } + + private static long[] getLongIntArray(Resources r, int resid) { + int[] ar = r.getIntArray(resid); + if (ar == null) { + return null; + } + long[] out = new long[ar.length]; + for (int i = 0; i < ar.length; i++) { + out[i] = ar[i]; + } + return out; + } + /** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */ private final class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler) { diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java new file mode 100644 index 000000000000..f76c1a1b2b9d --- /dev/null +++ b/services/core/java/com/android/server/vibrator/VibratorController.java @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vibrator; + +import android.annotation.Nullable; +import android.hardware.vibrator.IVibrator; +import android.os.Binder; +import android.os.IVibratorStateListener; +import android.os.RemoteCallbackList; +import android.os.RemoteException; +import android.os.VibrationEffect; +import android.os.Vibrator; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; + +import libcore.util.NativeAllocationRegistry; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** Controls a single vibrator. */ +// TODO(b/159207608): Make this package-private once vibrator services are moved to this package +public final class VibratorController { + private static final String TAG = "VibratorController"; + + private final Object mLock = new Object(); + private final NativeWrapper mNativeWrapper; + private final int mVibratorId; + private final long mCapabilities; + @Nullable + private final Set<Integer> mSupportedEffects; + @Nullable + private final Set<Integer> mSupportedPrimitives; + + @GuardedBy("mLock") + private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners = + new RemoteCallbackList<>(); + @GuardedBy("mLock") + private boolean mIsVibrating; + @GuardedBy("mLock") + private boolean mIsUnderExternalControl; + + /** Listener for vibration completion callbacks from native. */ + public interface OnVibrationCompleteListener { + + /** Callback triggered when vibration is complete. */ + void onComplete(int vibratorId, long vibrationId); + } + + /** + * Initializes the native part of this controller, creating a global reference to given + * {@link OnVibrationCompleteListener} and returns a newly allocated native pointer. This + * wrapper is responsible for deleting this pointer by calling the method pointed + * by {@link #vibratorGetFinalizer()}. + * + * <p><b>Note:</b> Make sure the given implementation of {@link OnVibrationCompleteListener} + * do not hold any strong reference to the instance responsible for deleting the returned + * pointer, to avoid creating a cyclic GC root reference. + */ + static native long vibratorInit(int vibratorId, OnVibrationCompleteListener listener); + + /** + * Returns pointer to native function responsible for cleaning up the native pointer allocated + * and returned by {@link #vibratorInit(int, OnVibrationCompleteListener)}. + */ + static native long vibratorGetFinalizer(); + + static native boolean vibratorIsAvailable(long nativePtr); + + static native void vibratorOn(long nativePtr, long milliseconds, long vibrationId); + + static native void vibratorOff(long nativePtr); + + static native void vibratorSetAmplitude(long nativePtr, int amplitude); + + static native int[] vibratorGetSupportedEffects(long nativePtr); + + static native int[] vibratorGetSupportedPrimitives(long nativePtr); + + static native long vibratorPerformEffect( + long nativePtr, long effect, long strength, long vibrationId); + + static native void vibratorPerformComposedEffect(long nativePtr, + VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId); + + static native void vibratorSetExternalControl(long nativePtr, boolean enabled); + + static native long vibratorGetCapabilities(long nativePtr); + + static native void vibratorAlwaysOnEnable(long nativePtr, long id, long effect, long strength); + + static native void vibratorAlwaysOnDisable(long nativePtr, long id); + + public VibratorController(int vibratorId, OnVibrationCompleteListener listener) { + this(vibratorId, listener, new NativeWrapper()); + } + + @VisibleForTesting + public VibratorController(int vibratorId, OnVibrationCompleteListener listener, + NativeWrapper nativeWrapper) { + mVibratorId = vibratorId; + mNativeWrapper = nativeWrapper; + + nativeWrapper.init(vibratorId, listener); + mCapabilities = nativeWrapper.getCapabilities(); + mSupportedEffects = asSet(nativeWrapper.getSupportedEffects()); + mSupportedPrimitives = asSet(nativeWrapper.getSupportedPrimitives()); + } + + /** Register state listener for this vibrator. */ + public boolean registerVibratorStateListener(IVibratorStateListener listener) { + synchronized (mLock) { + final long token = Binder.clearCallingIdentity(); + try { + if (!mVibratorStateListeners.register(listener)) { + return false; + } + // Notify its callback after new client registered. + notifyStateListenerLocked(listener); + return true; + } finally { + Binder.restoreCallingIdentity(token); + } + } + } + + /** Remove registered state listener for this vibrator. */ + public boolean unregisterVibratorStateListener(IVibratorStateListener listener) { + synchronized (mLock) { + final long token = Binder.clearCallingIdentity(); + try { + return mVibratorStateListeners.unregister(listener); + } finally { + Binder.restoreCallingIdentity(token); + } + } + } + + /** Return the id of the vibrator controlled by this instance. */ + public int getVibratorId() { + return mVibratorId; + } + + /** + * Return {@code true} is this vibrator is currently vibrating, false otherwise. + * + * <p>This state is controlled by calls to {@link #on} and {@link #off} methods, and is + * automatically notified to any registered {@link IVibratorStateListener} on change. + */ + public boolean isVibrating() { + synchronized (mLock) { + return mIsVibrating; + } + } + + /** Return {@code true} if this vibrator is under external control, false otherwise. */ + public boolean isUnderExternalControl() { + synchronized (mLock) { + return mIsUnderExternalControl; + } + } + + /** + * Check against this vibrator capabilities. + * + * @param capability one of IVibrator.CAP_* + * @return true if this vibrator has this capability, false otherwise + */ + public boolean hasCapability(long capability) { + return (mCapabilities & capability) == capability; + } + + /** + * Check against this vibrator supported effects. + * + * @param effectIds list of effects, one of VibrationEffect.EFFECT_* + * @return one entry per requested effectId, with one of Vibrator.VIBRATION_EFFECT_SUPPORT_* + */ + public int[] areEffectsSupported(int[] effectIds) { + int[] supported = new int[effectIds.length]; + if (mSupportedEffects == null) { + Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN); + } else { + for (int i = 0; i < effectIds.length; i++) { + supported[i] = mSupportedEffects.contains(effectIds[i]) + ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES + : Vibrator.VIBRATION_EFFECT_SUPPORT_NO; + } + } + return supported; + } + + /** + * Check against this vibrator supported primitives. + * + * @param primitiveIds list of primitives, one of VibrationEffect.Composition.EFFECT_* + * @return one entry per requested primitiveId, with true if it is supported + */ + public boolean[] arePrimitivesSupported(int[] primitiveIds) { + boolean[] supported = new boolean[primitiveIds.length]; + if (mSupportedPrimitives != null && hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { + for (int i = 0; i < primitiveIds.length; i++) { + supported[i] = mSupportedPrimitives.contains(primitiveIds[i]); + } + } + return supported; + } + + /** Return {@code true} if the underlying vibrator is currently available, false otherwise. */ + public boolean isAvailable() { + return mNativeWrapper.isAvailable(); + } + + /** + * Set the vibrator control to be external or not, based on given flag. + * + * <p>This will affect the state of {@link #isUnderExternalControl()}. + */ + public void setExternalControl(boolean externalControl) { + if (!hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { + return; + } + synchronized (mLock) { + mIsUnderExternalControl = externalControl; + mNativeWrapper.setExternalControl(externalControl); + } + } + + /** + * Update the predefined vibration effect saved with given id. This will remove the saved effect + * if given {@code effect} is {@code null}. + */ + public void updateAlwaysOn(int id, @Nullable VibrationEffect.Prebaked effect) { + if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + return; + } + synchronized (mLock) { + if (effect == null) { + mNativeWrapper.alwaysOnDisable(id); + } else { + mNativeWrapper.alwaysOnEnable(id, effect.getId(), effect.getEffectStrength()); + } + } + } + + /** Set the vibration amplitude. This will NOT affect the state of {@link #isVibrating()}. */ + public void setAmplitude(int amplitude) { + synchronized (mLock) { + if (hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { + mNativeWrapper.setAmplitude(amplitude); + } + } + } + + /** + * Turn on the vibrator for {@code milliseconds} time, using {@code vibrationId} or completion + * callback to {@link OnVibrationCompleteListener}. + * + * <p>This will affect the state of {@link #isVibrating()}. + */ + public void on(long milliseconds, long vibrationId) { + synchronized (mLock) { + mNativeWrapper.on(milliseconds, vibrationId); + notifyVibratorOnLocked(); + } + } + + /** + * Plays predefined vibration effect, using {@code vibrationId} or completion callback to + * {@link OnVibrationCompleteListener}. + * + * <p>This will affect the state of {@link #isVibrating()}. + */ + public long on(VibrationEffect.Prebaked effect, long vibrationId) { + synchronized (mLock) { + long duration = mNativeWrapper.perform(effect.getId(), effect.getEffectStrength(), + vibrationId); + if (duration > 0) { + notifyVibratorOnLocked(); + } + return duration; + } + } + + /** + * Plays composited vibration effect, using {@code vibrationId} or completion callback to + * {@link OnVibrationCompleteListener}. + * + * <p>This will affect the state of {@link #isVibrating()}. + */ + public void on(VibrationEffect.Composed effect, long vibrationId) { + if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { + return; + } + synchronized (mLock) { + mNativeWrapper.compose(effect.getPrimitiveEffects().toArray( + new VibrationEffect.Composition.PrimitiveEffect[0]), vibrationId); + notifyVibratorOnLocked(); + } + } + + /** Turns off the vibrator.This will affect the state of {@link #isVibrating()}. */ + public void off() { + synchronized (mLock) { + mNativeWrapper.off(); + notifyVibratorOffLocked(); + } + } + + @Override + public String toString() { + return "VibratorController{" + + "mVibratorId=" + mVibratorId + + ", mCapabilities=" + mCapabilities + + ", mSupportedEffects=" + mSupportedEffects + + ", mSupportedPrimitives=" + mSupportedPrimitives + + ", mIsVibrating=" + mIsVibrating + + ", mIsUnderExternalControl=" + mIsUnderExternalControl + + ", mVibratorStateListeners count=" + + mVibratorStateListeners.getRegisteredCallbackCount() + + '}'; + } + + @GuardedBy("mLock") + private void notifyVibratorOnLocked() { + if (!mIsVibrating) { + mIsVibrating = true; + notifyStateListenersLocked(); + } + } + + @GuardedBy("mLock") + private void notifyVibratorOffLocked() { + if (mIsVibrating) { + mIsVibrating = false; + notifyStateListenersLocked(); + } + } + + @GuardedBy("mLock") + private void notifyStateListenersLocked() { + final int length = mVibratorStateListeners.beginBroadcast(); + try { + for (int i = 0; i < length; i++) { + notifyStateListenerLocked(mVibratorStateListeners.getBroadcastItem(i)); + } + } finally { + mVibratorStateListeners.finishBroadcast(); + } + } + + @GuardedBy("mLock") + private void notifyStateListenerLocked(IVibratorStateListener listener) { + try { + listener.onVibrating(mIsVibrating); + } catch (RemoteException | RuntimeException e) { + Slog.e(TAG, "Vibrator state listener failed to call", e); + } + } + + @Nullable + private static Set<Integer> asSet(int[] values) { + if (values == null) { + return null; + } + HashSet<Integer> set = new HashSet<>(); + for (int value : values) { + set.add(value); + } + return set; + } + + /** Wrapper around the static-native methods of {@link VibratorController} for tests. */ + @VisibleForTesting + public static class NativeWrapper { + + private long mNativePtr = 0; + + /** Initializes native controller and allocation registry to destroy native instances. */ + public void init(int vibratorId, OnVibrationCompleteListener listener) { + mNativePtr = VibratorController.vibratorInit(vibratorId, listener); + long finalizerPtr = VibratorController.vibratorGetFinalizer(); + + if (finalizerPtr != 0) { + NativeAllocationRegistry registry = + NativeAllocationRegistry.createMalloced( + VibratorController.class.getClassLoader(), finalizerPtr); + registry.registerNativeAllocation(this, mNativePtr); + } + } + + /** Check if the vibrator is currently available. */ + public boolean isAvailable() { + return VibratorController.vibratorIsAvailable(mNativePtr); + } + + /** Turns vibrator on for given time. */ + public void on(long milliseconds, long vibrationId) { + VibratorController.vibratorOn(mNativePtr, milliseconds, vibrationId); + } + + /** Turns vibrator off. */ + public void off() { + VibratorController.vibratorOff(mNativePtr); + } + + /** Sets the amplitude for the vibrator to run. */ + public void setAmplitude(int amplitude) { + VibratorController.vibratorSetAmplitude(mNativePtr, amplitude); + } + + /** Returns all predefined effects supported by the device vibrator. */ + public int[] getSupportedEffects() { + return VibratorController.vibratorGetSupportedEffects(mNativePtr); + } + + /** Returns all compose primitives supported by the device vibrator. */ + public int[] getSupportedPrimitives() { + return VibratorController.vibratorGetSupportedPrimitives(mNativePtr); + } + + /** Turns vibrator on to perform one of the supported effects. */ + public long perform(long effect, long strength, long vibrationId) { + return VibratorController.vibratorPerformEffect( + mNativePtr, effect, strength, vibrationId); + } + + /** Turns vibrator on to perform one of the supported composed effects. */ + public void compose( + VibrationEffect.Composition.PrimitiveEffect[] effect, long vibrationId) { + VibratorController.vibratorPerformComposedEffect(mNativePtr, effect, + vibrationId); + } + + /** Enabled the device vibrator to be controlled by another service. */ + public void setExternalControl(boolean enabled) { + VibratorController.vibratorSetExternalControl(mNativePtr, enabled); + } + + /** Returns all capabilities of the device vibrator. */ + public long getCapabilities() { + return VibratorController.vibratorGetCapabilities(mNativePtr); + } + + /** Enable always-on vibration with given id and effect. */ + public void alwaysOnEnable(long id, long effect, long strength) { + VibratorController.vibratorAlwaysOnEnable(mNativePtr, id, effect, strength); + } + + /** Disable always-on vibration for given id. */ + public void alwaysOnDisable(long id) { + VibratorController.vibratorAlwaysOnDisable(mNativePtr, id); + } + } +} diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c2016decdbe9..913c3e580adf 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -7584,6 +7584,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET; } + String getProcessName() { + return info.applicationInfo.processName; + } + int getUid() { return info.applicationInfo.uid; } @@ -7596,6 +7600,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return app != null ? app.getPid() : 0; } + int getLaunchedFromPid() { + return launchedFromPid; + } + + int getLaunchedFromUid() { + return launchedFromUid; + } + /** * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index acee7b26725e..b88b54ef08f5 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -57,9 +57,6 @@ import static android.view.WindowManager.TRANSIT_OPEN; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS; -import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME; -import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP; -import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS; @@ -71,6 +68,9 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.ActivityTaskManagerService.ANIMATE; +import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME; +import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP; +import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY; import static com.android.server.wm.Task.ActivityState.RESUMED; @@ -1870,7 +1870,7 @@ class ActivityStarter { } mSupervisor.getLaunchParamsController().calculate(targetTask, r.info.windowLayout, r, - sourceRecord, mOptions, PHASE_BOUNDS, mLaunchParams); + sourceRecord, mOptions, PHASE_BOUNDS, mLaunchParams, mRequest); mPreferredTaskDisplayArea = mLaunchParams.hasPreferredTaskDisplayArea() ? mLaunchParams.mPreferredTaskDisplayArea : mRootWindowContainer.getDefaultTaskDisplayArea(); @@ -2031,12 +2031,12 @@ class ActivityStarter { */ private int deliverToCurrentTopIfNeeded(Task topStack, NeededUriGrants intentGrants) { final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); - final boolean dontStart = top != null && mStartActivity.resultTo == null + final boolean dontStart = top != null && top.mActivityComponent.equals(mStartActivity.mActivityComponent) && top.mUserId == mStartActivity.mUserId && top.attachedToProcess() && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 - || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) + || LAUNCH_SINGLE_TOP == mLaunchMode) // This allows home activity to automatically launch on secondary task display area // when it was added, if home was the top activity on default task display area, // instead of sending new intent to the home activity on default display area. @@ -2057,6 +2057,13 @@ class ActivityStarter { return START_RETURN_INTENT_TO_CALLER; } + if (mStartActivity.resultTo != null) { + mStartActivity.resultTo.sendResult(INVALID_UID, mStartActivity.resultWho, + mStartActivity.requestCode, RESULT_CANCELED, + null /* data */, null /* dataGrants */); + mStartActivity.resultTo = null; + } + deliverNewIntent(top, intentGrants); // Don't use mStartActivity.task to show the toast. We're not starting a new activity but @@ -2254,7 +2261,7 @@ class ActivityStarter { // Preferred display id is the only state we need for now and it could be updated again // after we located a reusable task (which might be resided in another display). mSupervisor.getLaunchParamsController().calculate(inTask, r.info.windowLayout, r, - sourceRecord, options, PHASE_DISPLAY, mLaunchParams); + sourceRecord, options, PHASE_DISPLAY, mLaunchParams, mRequest); mPreferredTaskDisplayArea = mLaunchParams.hasPreferredTaskDisplayArea() ? mLaunchParams.mPreferredTaskDisplayArea : mRootWindowContainer.getDefaultTaskDisplayArea(); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 27faf13e2999..e12dc2bd56a8 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -1056,7 +1056,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void onUserUnlocking(@NonNull TargetUser user) { + public void onUserUnlocked(@NonNull TargetUser user) { synchronized (mService.getGlobalLock()) { mService.mTaskSupervisor.onUserUnlocked(user.getUserIdentifier()); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 1064e6aa357c..d0c26af82d99 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -186,7 +186,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { private static final int RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 13; private static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14; private static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15; - private static final int REPORT_HOME_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 16; + private static final int START_HOME_MSG = FIRST_SUPERVISOR_STACK_MSG + 16; private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 17; // Used to indicate that windows of activities should be preserved during the resize. @@ -446,6 +446,9 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // unlocked. mPersisterQueue.startPersisting(); mLaunchParamsPersister.onUnlockUser(userId); + + // Need to launch home again for those displays that do not have encryption aware home app. + scheduleStartHome("userUnlocked"); } public ActivityMetricsLogger getActivityMetricsLogger() { @@ -956,13 +959,17 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { void updateHomeProcess(WindowProcessController app) { if (app != null && mService.mHomeProcess != app) { - if (!mHandler.hasMessages(REPORT_HOME_CHANGED_MSG)) { - mHandler.sendEmptyMessage(REPORT_HOME_CHANGED_MSG); - } + scheduleStartHome("homeChanged"); mService.mHomeProcess = app; } } + private void scheduleStartHome(String reason) { + if (!mHandler.hasMessages(START_HOME_MSG)) { + mHandler.obtainMessage(START_HOME_MSG, reason).sendToTarget(); + } + } + private void logIfTransactionTooLarge(Intent intent, Bundle icicle) { int extrasSize = 0; if (intent != null) { @@ -2473,11 +2480,11 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { handleLaunchTaskBehindCompleteLocked(r); } } break; - case REPORT_HOME_CHANGED_MSG: { - mHandler.removeMessages(REPORT_HOME_CHANGED_MSG); + case START_HOME_MSG: { + mHandler.removeMessages(START_HOME_MSG); // Start home activities on displays with no activities. - mRootWindowContainer.startHomeOnEmptyDisplays("homeChanged"); + mRootWindowContainer.startHomeOnEmptyDisplays((String) msg.obj); } break; case TOP_RESUMED_STATE_LOSS_TIMEOUT_MSG: { final ActivityRecord r = (ActivityRecord) msg.obj; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 4133ea2b2a7b..ccc85f834bc1 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -73,6 +73,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.DisplayAreaOrganizer.FEATURE_ROOT; @@ -91,7 +93,7 @@ import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_C import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.DisplayContentProto.APP_TRANSITION; -import static com.android.server.wm.DisplayContentProto.CAN_SHOW_IME; +import static com.android.server.wm.DisplayContentProto.IME_POLICY; import static com.android.server.wm.DisplayContentProto.CLOSING_APPS; import static com.android.server.wm.DisplayContentProto.CURRENT_FOCUS; import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES; @@ -203,6 +205,7 @@ import android.view.SurfaceControl.Transaction; import android.view.SurfaceSession; import android.view.WindowInsets; import android.view.WindowManager; +import android.view.WindowManager.DisplayImePolicy; import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.internal.annotations.VisibleForTesting; @@ -2930,7 +2933,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mInsetsStateController.getImeSourceProvider().dumpDebug(proto, IME_INSETS_SOURCE_PROVIDER, logLevel); } - proto.write(CAN_SHOW_IME, canShowIme()); + proto.write(IME_POLICY, getImePolicy()); proto.end(token); } @@ -3561,7 +3564,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * @return {@link InsetsControlTarget} that can host IME. */ InsetsControlTarget getImeHostOrFallback(WindowState target) { - if (target != null && target.getDisplayContent().canShowIme()) { + if (target != null + && target.getDisplayContent().getImePolicy() == DISPLAY_IME_POLICY_LOCAL) { return target; } return getImeFallback(); @@ -3575,12 +3579,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return statusBar != null ? statusBar : defaultDc.mRemoteInsetsControlTarget; } - boolean canShowIme() { + @DisplayImePolicy int getImePolicy() { if (!isTrusted()) { - return false; + return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; + } + final int imePolicy = mWmService.mDisplayWindowSettings.getImePolicyLocked(this); + if (imePolicy == DISPLAY_IME_POLICY_FALLBACK_DISPLAY && forceDesktopMode()) { + // If the display has not explicitly requested for the IME to be hidden then it shall + // show the IME locally. + return DISPLAY_IME_POLICY_LOCAL; } - return mWmService.mDisplayWindowSettings.shouldShowImeLocked(this) - || forceDesktopMode(); + return imePolicy; } boolean forceDesktopMode() { diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index f14a2ee8e7ee..826b7259a9ff 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -66,7 +66,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BA import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; @@ -279,7 +278,6 @@ public class DisplayPolicy { private volatile boolean mKeyguardDrawComplete; private volatile boolean mWindowManagerDrawComplete; - private final ArraySet<WindowState> mScreenDecorWindows = new ArraySet<>(); private WindowState mStatusBar = null; private WindowState mNotificationShade = null; private final int[] mStatusBarHeightForRotation = new int[4]; @@ -864,19 +862,7 @@ public class DisplayPolicy { * @param attrs The window layout parameters to be modified. These values * are modified in-place. */ - public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs, - int callingPid, int callingUid) { - - final boolean isScreenDecor = (attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0; - if (mScreenDecorWindows.contains(win)) { - if (!isScreenDecor) { - // No longer has the flag set, so remove from the set. - mScreenDecorWindows.remove(win); - } - } else if (isScreenDecor && hasStatusBarServicePermission(callingPid, callingUid)) { - mScreenDecorWindows.add(win); - } - + public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs) { switch (attrs.type) { case TYPE_SYSTEM_OVERLAY: case TYPE_SECURE_SYSTEM_OVERLAY: @@ -966,11 +952,6 @@ public class DisplayPolicy { * WindowManagerImpl.ADD_MULTIPLE_SINGLETON */ int validateAddingWindowLw(WindowManager.LayoutParams attrs, int callingPid, int callingUid) { - if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) { - mContext.enforcePermission( - android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid, - "DisplayPolicy"); - } if ((attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0) { mContext.enforcePermission( android.Manifest.permission.INTERNAL_SYSTEM_WINDOW, callingPid, callingUid, @@ -1090,10 +1071,6 @@ public class DisplayPolicy { * @param attrs Information about the window to be added. */ void addWindowLw(WindowState win, WindowManager.LayoutParams attrs) { - if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) { - mScreenDecorWindows.add(win); - } - switch (attrs.type) { case TYPE_NOTIFICATION_SHADE: mNotificationShade = win; @@ -1275,7 +1252,6 @@ public class DisplayPolicy { if (mLastFocusedWindow == win) { mLastFocusedWindow = null; } - mScreenDecorWindows.remove(win); } private int getStatusBarHeight(DisplayFrames displayFrames) { @@ -1457,14 +1433,12 @@ public class DisplayPolicy { } final int fl = attrs.flags; - final int pfl = attrs.privateFlags; final boolean layoutInScreenAndInsetDecor = (fl & FLAG_LAYOUT_IN_SCREEN) != 0 && (fl & FLAG_LAYOUT_INSET_DECOR) != 0; - final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0; final DisplayFrames displayFrames = isFixedRotationTransforming ? windowToken.getFixedRotationTransformDisplayFrames() : mDisplayContent.mDisplayFrames; - if (layoutInScreenAndInsetDecor && !screenDecor) { + if (layoutInScreenAndInsetDecor) { outDisplayCutout.set( displayFrames.mDisplayCutout.calculateRelativeTo(outFrame).getDisplayCutout()); } else { @@ -1564,7 +1538,6 @@ public class DisplayPolicy { simulatedWindowFrames, barContentFrames, contentFrame -> layoutStatusBar(displayFrames, contentFrame)); } - layoutScreenDecorWindows(displayFrames, simulatedWindowFrames); } /** @@ -1585,7 +1558,6 @@ public class DisplayPolicy { layoutNavigationBar(displayFrames, uiMode, null /* simulatedContentFrame */); layoutStatusBar(displayFrames, null /* simulatedContentFrame */); - layoutScreenDecorWindows(displayFrames, null /* simulatedFrames */); } void updateHideNavInputEventReceiver() { @@ -1640,47 +1612,6 @@ public class DisplayPolicy { state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(u.left, s.bottom, u.right, u.bottom); } - /** - * Layout the decor windows with {@link #PRIVATE_FLAG_IS_SCREEN_DECOR}. - * - * @param displayFrames The display frames to be layouted. - * @param simulatedFrames Non-null if the caller only needs the result of display frames (see - * {@link WindowState#mSimulatedWindowFrames}). - */ - private void layoutScreenDecorWindows(DisplayFrames displayFrames, - WindowFrames simulatedFrames) { - if (mScreenDecorWindows.isEmpty()) { - return; - } - - sTmpRect.setEmpty(); - final int displayId = displayFrames.mDisplayId; - - for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) { - final WindowState w = mScreenDecorWindows.valueAt(i); - if (w.getDisplayId() != displayId || !w.isVisible()) { - // Skip if not on the same display or not visible. - continue; - } - - final boolean isSimulatedLayout = simulatedFrames != null; - if (isSimulatedLayout) { - w.setSimulatedWindowFrames(simulatedFrames); - } - getRotatedWindowBounds(displayFrames, w, sTmpScreenDecorFrame); - final WindowFrames windowFrames = w.getLayoutingWindowFrames(); - windowFrames.setFrames(sTmpScreenDecorFrame /* parentFrame */, - sTmpScreenDecorFrame /* displayFrame */); - try { - w.computeFrame(displayFrames); - } finally { - if (isSimulatedLayout) { - w.setSimulatedWindowFrames(null); - } - } - } - } - private void layoutStatusBar(DisplayFrames displayFrames, Rect simulatedContentFrame) { // decide where the status bar goes ahead of time if (mStatusBar == null) { @@ -1819,8 +1750,7 @@ public class DisplayPolicy { // We've already done the navigation bar, status bar, and all screen decor windows. If the // status bar can receive input, we need to layout it again to accommodate for the IME // window. - if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar - || mScreenDecorWindows.contains(win)) { + if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) { return; } final WindowManager.LayoutParams attrs = win.getAttrs(); @@ -2772,7 +2702,11 @@ public class DisplayPolicy { && mLastDockedStackBounds.equals(mDockedStackBounds)) { return false; } - + if (mDisplayContent.isDefaultDisplay && mLastFocusIsFullscreen != isFullscreen + && ((mLastAppearance ^ appearance) & APPEARANCE_LOW_PROFILE_BARS) != 0) { + mService.mInputManager.setSystemUiLightsOut( + isFullscreen || (appearance & APPEARANCE_LOW_PROFILE_BARS) != 0); + } mLastDisableFlags = disableFlags; mLastAppearance = appearance; mLastFullscreenAppearance = fullscreenAppearance; @@ -2802,10 +2736,6 @@ public class DisplayPolicy { } }); - if (mDisplayContent.isDefaultDisplay) { - mService.mInputManager.setSystemUiLightsOut( - isFullscreen || (appearance & APPEARANCE_LOW_PROFILE_BARS) != 0); - } return true; } diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index 472678cf8e37..5d4dbc8388c4 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -19,6 +19,8 @@ package com.android.server.wm; import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO; import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED; @@ -31,6 +33,7 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.IWindowManager; import android.view.Surface; +import android.view.WindowManager.DisplayImePolicy; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.DisplayContent.ForceScalingMode; @@ -212,22 +215,23 @@ class DisplayWindowSettings { mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); } - boolean shouldShowImeLocked(DisplayContent dc) { + @DisplayImePolicy int getImePolicyLocked(DisplayContent dc) { if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) { // Default display should show IME. - return true; + return DISPLAY_IME_POLICY_LOCAL; } final DisplayInfo displayInfo = dc.getDisplayInfo(); final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo); - return settings.mShouldShowIme != null ? settings.mShouldShowIme : false; + return settings.mImePolicy != null ? settings.mImePolicy + : DISPLAY_IME_POLICY_FALLBACK_DISPLAY; } - void setShouldShowImeLocked(DisplayContent dc, boolean shouldShow) { + void setDisplayImePolicy(DisplayContent dc, @DisplayImePolicy int imePolicy) { final DisplayInfo displayInfo = dc.getDisplayInfo(); final SettingsProvider.SettingsEntry overrideSettings = mSettingsProvider.getOverrideSettings(displayInfo); - overrideSettings.mShouldShowIme = shouldShow; + overrideSettings.mImePolicy = imePolicy; mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); } @@ -343,7 +347,7 @@ class DisplayWindowSettings { @Nullable Boolean mShouldShowSystemDecors; @Nullable - Boolean mShouldShowIme; + Integer mImePolicy; @Nullable Integer mFixedToUserRotation; @Nullable @@ -406,8 +410,8 @@ class DisplayWindowSettings { mShouldShowSystemDecors = other.mShouldShowSystemDecors; changed = true; } - if (other.mShouldShowIme != mShouldShowIme) { - mShouldShowIme = other.mShouldShowIme; + if (!Objects.equals(other.mImePolicy, mImePolicy)) { + mImePolicy = other.mImePolicy; changed = true; } if (!Objects.equals(other.mFixedToUserRotation, mFixedToUserRotation)) { @@ -481,9 +485,9 @@ class DisplayWindowSettings { mShouldShowSystemDecors = delta.mShouldShowSystemDecors; changed = true; } - if (delta.mShouldShowIme != null - && delta.mShouldShowIme != mShouldShowIme) { - mShouldShowIme = delta.mShouldShowIme; + if (delta.mImePolicy != null + && !Objects.equals(delta.mImePolicy, mImePolicy)) { + mImePolicy = delta.mImePolicy; changed = true; } if (delta.mFixedToUserRotation != null @@ -509,7 +513,7 @@ class DisplayWindowSettings { && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED && mShouldShowWithInsecureKeyguard == null && mShouldShowSystemDecors == null - && mShouldShowIme == null + && mImePolicy == null && mFixedToUserRotation == null && mIgnoreOrientationRequest == null; } @@ -530,7 +534,7 @@ class DisplayWindowSettings { && Objects.equals(mShouldShowWithInsecureKeyguard, that.mShouldShowWithInsecureKeyguard) && Objects.equals(mShouldShowSystemDecors, that.mShouldShowSystemDecors) - && Objects.equals(mShouldShowIme, that.mShouldShowIme) + && Objects.equals(mImePolicy, that.mImePolicy) && Objects.equals(mFixedToUserRotation, that.mFixedToUserRotation) && Objects.equals(mIgnoreOrientationRequest, that.mIgnoreOrientationRequest); @@ -540,7 +544,7 @@ class DisplayWindowSettings { public int hashCode() { return Objects.hash(mWindowingMode, mUserRotationMode, mUserRotation, mForcedWidth, mForcedHeight, mForcedDensity, mForcedScalingMode, mRemoveContentMode, - mShouldShowWithInsecureKeyguard, mShouldShowSystemDecors, mShouldShowIme, + mShouldShowWithInsecureKeyguard, mShouldShowSystemDecors, mImePolicy, mFixedToUserRotation, mIgnoreOrientationRequest); } @@ -557,7 +561,7 @@ class DisplayWindowSettings { + ", mRemoveContentMode=" + mRemoveContentMode + ", mShouldShowWithInsecureKeyguard=" + mShouldShowWithInsecureKeyguard + ", mShouldShowSystemDecors=" + mShouldShowSystemDecors - + ", mShouldShowIme=" + mShouldShowIme + + ", mShouldShowIme=" + mImePolicy + ", mFixedToUserRotation=" + mFixedToUserRotation + ", mIgnoreOrientationRequest=" + mIgnoreOrientationRequest + '}'; diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java index 83da136e2005..78f1426348a7 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java @@ -16,7 +16,9 @@ package com.android.server.wm; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; @@ -35,13 +37,11 @@ import android.view.DisplayAddress; import android.view.DisplayInfo; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; import com.android.server.wm.DisplayWindowSettings.SettingsProvider; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; import java.io.File; import java.io.FileNotFoundException; @@ -49,7 +49,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -390,8 +389,15 @@ class DisplayWindowSettingsProvider implements SettingsProvider { "shouldShowWithInsecureKeyguard", null /* defaultValue */); settingsEntry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors", null /* defaultValue */); - settingsEntry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme", + final Boolean shouldShowIme = getBooleanAttribute(parser, "shouldShowIme", null /* defaultValue */); + if (shouldShowIme != null) { + settingsEntry.mImePolicy = shouldShowIme ? DISPLAY_IME_POLICY_LOCAL + : DISPLAY_IME_POLICY_FALLBACK_DISPLAY; + } else { + settingsEntry.mImePolicy = getIntegerAttribute(parser, "imePolicy", + null /* defaultValue */); + } settingsEntry.mFixedToUserRotation = getIntegerAttribute(parser, "fixedToUserRotation", null /* defaultValue */); settingsEntry.mIgnoreOrientationRequest = getBooleanAttribute(parser, @@ -478,9 +484,8 @@ class DisplayWindowSettingsProvider implements SettingsProvider { out.attribute(null, "shouldShowSystemDecors", settingsEntry.mShouldShowSystemDecors.toString()); } - if (settingsEntry.mShouldShowIme != null) { - out.attribute(null, "shouldShowIme", - settingsEntry.mShouldShowIme.toString()); + if (settingsEntry.mImePolicy != null) { + out.attributeInt(null, "imePolicy", settingsEntry.mImePolicy); } if (settingsEntry.mFixedToUserRotation != null) { out.attribute(null, "fixedToUserRotation", diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index c3b6149482e2..ebd91a093326 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -206,9 +206,8 @@ class KeyguardController { mAodShowing ? 1 : 0, 1 /* keyguardGoingAway */, "keyguardGoingAway"); - mRootWindowContainer.getDefaultDisplay() - .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, - convertTransitFlags(flags)); + mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare( + TRANSIT_KEYGUARD_GOING_AWAY, convertTransitFlags(flags)); updateKeyguardSleepToken(); // Some stack visibility might change (e.g. docked stack) diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java index f1ae921c87f5..b6b172eeae5b 100644 --- a/services/core/java/com/android/server/wm/LaunchParamsController.java +++ b/services/core/java/com/android/server/wm/LaunchParamsController.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.Display.INVALID_DISPLAY; +import static com.android.server.wm.ActivityStarter.Request; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_DONE; @@ -73,9 +74,10 @@ class LaunchParamsController { * @param source The {@link ActivityRecord} from which activity was started from. * @param options The {@link ActivityOptions} specified for the activity. * @param result The resulting params. + * @param request The optional request from the activity starter. */ - void calculate(Task task, WindowLayout layout, ActivityRecord activity, - ActivityRecord source, ActivityOptions options, int phase, LaunchParams result) { + void calculate(Task task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, + ActivityOptions options, int phase, LaunchParams result, @Nullable Request request) { result.reset(); if (task != null || activity != null) { @@ -91,7 +93,7 @@ class LaunchParamsController { final LaunchParamsModifier modifier = mModifiers.get(i); switch(modifier.onCalculate(task, layout, activity, source, options, phase, mTmpCurrent, - mTmpResult)) { + mTmpResult, request)) { case RESULT_SKIP: // Do not apply any results when we are told to skip continue; @@ -128,7 +130,8 @@ class LaunchParamsController { boolean layoutTask(Task task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options) { - calculate(task, layout, activity, source, options, PHASE_BOUNDS, mTmpParams); + calculate(task, layout, activity, source, options, PHASE_BOUNDS, mTmpParams, + null /* request */); // No changes, return. if (mTmpParams.isEmpty()) { @@ -305,15 +308,17 @@ class LaunchParamsController { * launched should have this be non-null. * @param source the Activity that launched a new task. Could be {@code null}. * @param options {@link ActivityOptions} used to start the activity with. - * @param phase the calculation phase, see {@link LaunchParamsModifier.Phase} + * @param phase the calculation phase, see {@link Phase} * @param currentParams launching params after the process of last {@link * LaunchParamsModifier}. * @param outParams the result params to be set. + * @param request Optional data to give more context on the launch * @return see {@link LaunchParamsModifier.Result} */ @Result - int onCalculate(Task task, WindowLayout layout, ActivityRecord activity, + int onCalculate(@Nullable Task task, WindowLayout layout, ActivityRecord activity, ActivityRecord source, ActivityOptions options, @Phase int phase, - LaunchParams currentParams, LaunchParams outParams); + LaunchParams currentParams, LaunchParams outParams, + @Nullable Request request); } } diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 6dc957c1d118..8b2fa52afd22 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -35,6 +35,7 @@ import static android.util.DisplayMetrics.DENSITY_DEFAULT; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static com.android.server.wm.ActivityStarter.Request; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -99,23 +100,25 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { ActivityRecord source, ActivityOptions options, LaunchParams currentParams, LaunchParams outParams) { return onCalculate(task, layout, activity, source, options, PHASE_BOUNDS, currentParams, - outParams); + outParams, null); } @Override - public int onCalculate(Task task, ActivityInfo.WindowLayout layout, - ActivityRecord activity, ActivityRecord source, ActivityOptions options, - int phase, LaunchParams currentParams, LaunchParams outParams) { + public int onCalculate(@Nullable Task task, @NonNull ActivityInfo.WindowLayout layout, + @NonNull ActivityRecord activity, @Nullable ActivityRecord source, + ActivityOptions options, int phase, LaunchParams currentParams, LaunchParams outParams, + @Nullable Request request) { initLogBuilder(task, activity); final int result = calculate(task, layout, activity, source, options, phase, currentParams, - outParams); + outParams, request); outputLog(); return result; } - private int calculate(Task task, ActivityInfo.WindowLayout layout, - ActivityRecord activity, ActivityRecord source, ActivityOptions options, int phase, - LaunchParams currentParams, LaunchParams outParams) { + private int calculate(@Nullable Task task, @NonNull ActivityInfo.WindowLayout layout, + @NonNull ActivityRecord activity, @Nullable ActivityRecord source, + ActivityOptions options, int phase, LaunchParams currentParams, LaunchParams outParams, + @Nullable Request request) { final ActivityRecord root; if (task != null) { root = task.getRootActivity() == null ? activity : task.getRootActivity(); @@ -138,7 +141,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // STEP 1: Determine the display area to launch the activity/task. final TaskDisplayArea taskDisplayArea = getPreferredLaunchTaskDisplayArea(task, - options, source, currentParams); + options, source, currentParams, activity, request); outParams.mPreferredTaskDisplayArea = taskDisplayArea; // TODO(b/152116619): Update the usages of display to use taskDisplayArea below. final DisplayContent display = taskDisplayArea.mDisplayContent; @@ -298,7 +301,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { } private TaskDisplayArea getPreferredLaunchTaskDisplayArea(@Nullable Task task, - @Nullable ActivityOptions options, ActivityRecord source, LaunchParams currentParams) { + @Nullable ActivityOptions options, ActivityRecord source, LaunchParams currentParams, + @NonNull ActivityRecord activityRecord, @Nullable Request request) { TaskDisplayArea taskDisplayArea = null; final WindowContainerToken optionLaunchTaskDisplayAreaToken = options != null @@ -369,7 +373,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { taskDisplayArea = currentParams.mPreferredTaskDisplayArea; } - // Fallback to default display if the device didn't declare support for multi-display + // Re-route to default display if the device didn't declare support for multi-display if (taskDisplayArea != null && !mSupervisor.mService.mSupportsMultiDisplay && taskDisplayArea.getDisplayId() != DEFAULT_DISPLAY) { taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea(); @@ -377,7 +381,53 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { return (taskDisplayArea != null) ? taskDisplayArea - : mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea(); + : getFallbackDisplayAreaForActivity(activityRecord, request); + } + + /** + * Calculates the default {@link TaskDisplayArea} for a task. We attempt to put the activity + * within the same display area if possible. The strategy is to find the display in the + * following order: + * + * <ol> + * <li>The display area of the top activity from the launching process will be used</li> + * <li>The display area of the top activity from the real launching process will be used + * </li> + * <li>Default display area from the associated root window container.</li> + * </ol> + * @param activityRecord the activity being started + * @param request optional {@link Request} made to start the activity record + * @return {@link TaskDisplayArea} to house the task + */ + private TaskDisplayArea getFallbackDisplayAreaForActivity( + @NonNull ActivityRecord activityRecord, @Nullable Request request) { + + WindowProcessController controllerFromLaunchingRecord = mSupervisor.mService + .getProcessController(activityRecord.launchedFromPid, + activityRecord.launchedFromUid); + final TaskDisplayArea displayAreaForLaunchingRecord = controllerFromLaunchingRecord == null + ? null : controllerFromLaunchingRecord.getTopActivityDisplayArea(); + if (displayAreaForLaunchingRecord != null) { + return displayAreaForLaunchingRecord; + } + + WindowProcessController controllerFromProcess = mSupervisor.mService.getProcessController( + activityRecord.getProcessName(), activityRecord.getUid()); + final TaskDisplayArea displayAreaForRecord = controllerFromProcess == null ? null + : controllerFromProcess.getTopActivityDisplayArea(); + if (displayAreaForRecord != null) { + return displayAreaForRecord; + } + + WindowProcessController controllerFromRequest = request == null ? null : mSupervisor + .mService.getProcessController(request.realCallingPid, request.realCallingUid); + final TaskDisplayArea displayAreaFromSourceProcess = controllerFromRequest == null ? null + : controllerFromRequest.getTopActivityDisplayArea(); + if (displayAreaFromSourceProcess != null) { + return displayAreaFromSourceProcess; + } + + return mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea(); } private boolean canInheritWindowingModeFromSource(@NonNull DisplayContent display, diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 341694d8ecb2..0cdd055d4052 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -26,6 +26,7 @@ import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY; import android.annotation.IntDef; import android.annotation.NonNull; +import android.graphics.Point; import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; @@ -46,7 +47,6 @@ import com.android.internal.protolog.common.ProtoLog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -import java.util.Set; /** * Represents a logical transition. @@ -91,13 +91,24 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe private final BLASTSyncEngine mSyncEngine; /** + * This is a leash to put animating surfaces into flatly without clipping/ordering issues. It + * is a child of all the targets' shared ancestor. + */ + private SurfaceControl mRootLeash = null; + + /** * Contains change infos for both participants and all ancestors. We have to track ancestors * because they are all promotion candidates and thus we need their start-states * to be captured. */ final ArrayMap<WindowContainer, ChangeInfo> mChanges = new ArrayMap<>(); + /** The collected participants in the transition. */ final ArraySet<WindowContainer> mParticipants = new ArraySet<>(); + + /** The final animation targets derived from participants after promotion. */ + private ArraySet<WindowContainer> mTargets = null; + private @TransitionState int mState = STATE_COLLECTING; private boolean mReadyCalled = false; @@ -190,6 +201,42 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe if (mState < STATE_PLAYING) { throw new IllegalStateException("Can't finish a non-playing transition " + mSyncId); } + final Point tmpPos = new Point(); + // usually only size 1 + final ArraySet<DisplayContent> displays = new ArraySet<>(); + // Immediately apply all surface reparents, don't wait for pending/sync/etc. + SurfaceControl.Transaction t = mController.mAtm.mWindowManager.mTransactionFactory.get(); + for (int i = mTargets.size() - 1; i >= 0; --i) { + final WindowContainer target = mTargets.valueAt(i); + if (target.getParent() != null) { + // Ensure surfaceControls are re-parented back into the hierarchy. + t.reparent(target.getSurfaceControl(), target.getParent().getSurfaceControl()); + target.getRelativePosition(tmpPos); + t.setPosition(target.getSurfaceControl(), tmpPos.x, tmpPos.y); + displays.add(target.getDisplayContent()); + } + } + // Need to update layers on ALL displays (for now) since they were all paused while + // the animation played. + for (int i = displays.size() - 1; i >= 0; --i) { + if (displays.valueAt(i) == null) continue; + displays.valueAt(i).assignChildLayers(t); + } + // Also pro-actively hide going-invisible activity surfaces in same transaction to + // prevent flickers due to reparenting and animation z-order mismatch. + for (int i = mParticipants.size() - 1; i >= 0; --i) { + final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord(); + if (ar == null || ar.mVisibleRequested || !ar.isVisible()) continue; + t.hide(ar.getSurfaceControl()); + } + if (mRootLeash.isValid()) { + t.remove(mRootLeash); + } + mRootLeash = null; + t.apply(); + t.close(); + + // Commit all going-invisible containers for (int i = 0; i < mParticipants.size(); ++i) { final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord(); if (ar == null || ar.mVisibleRequested) { @@ -234,7 +281,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mState = STATE_PLAYING; mController.moveToPlaying(this); - final TransitionInfo info = calculateTransitionInfo(mType, mParticipants, mChanges); + + // Resolve the animating targets from the participants + mTargets = calculateTargets(mParticipants, mChanges); + final TransitionInfo info = calculateTransitionInfo(mType, mTargets, mChanges); + mRootLeash = info.getRootLeash(); handleNonAppWindowsInTransition(displayId, mType, mFlags); @@ -245,11 +296,14 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mController.getTransitionPlayer().onTransitionReady(this, info, transaction); } catch (RemoteException e) { // If there's an exception when trying to send the mergedTransaction to the - // client, we should immediately apply it here so the transactions aren't lost. + // client, we should finish and apply it here so the transactions aren't lost. transaction.apply(); + finishTransition(); } } else { + // No player registered, so just finish/apply immediately transaction.apply(); + finishTransition(); } mSyncId = -1; } @@ -325,10 +379,12 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe * * @return {@code true} if transition in target can be promoted to its parent. */ - private static boolean canPromote( - WindowContainer target, ArraySet<WindowContainer> topTargets) { + private static boolean canPromote(WindowContainer target, ArraySet<WindowContainer> topTargets, + ArrayMap<WindowContainer, ChangeInfo> changes) { final WindowContainer parent = target.getParent(); - if (parent == null || !parent.canCreateRemoteAnimationTarget()) { + final ChangeInfo parentChanges = parent != null ? changes.get(parent) : null; + if (parent == null || !parent.canCreateRemoteAnimationTarget() + || parentChanges == null || !parentChanges.hasChanged(parent)) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " SKIP: %s", parent == null ? "no parent" : ("parent can't be target " + parent)); return false; @@ -394,14 +450,14 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Go through each target until we find one that can be promoted. for (WindowContainer targ : topTargets) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " checking %s", targ); - if (!canPromote(targ, topTargets)) { + if (!canPromote(targ, topTargets, changes)) { continue; } - final WindowContainer parent = targ.getParent(); // No obstructions found to promotion, so promote + final WindowContainer parent = targ.getParent(); + final ChangeInfo parentInfo = changes.get(parent); ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " CAN PROMOTE: promoting to parent %s", parent); - final ChangeInfo parentInfo = changes.get(parent); targets.add(parent); // Go through all children of newly-promoted container and remove them from the @@ -443,10 +499,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe * animation targets to higher level in the window hierarchy if possible. */ @VisibleForTesting - static TransitionInfo calculateTransitionInfo(int type, Set<WindowContainer> participants, + @NonNull + static ArraySet<WindowContainer> calculateTargets(ArraySet<WindowContainer> participants, ArrayMap<WindowContainer, ChangeInfo> changes) { - final TransitionInfo out = new TransitionInfo(type); - ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Start calculating TransitionInfo based on participants: %s", participants); @@ -470,6 +525,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // Search through ancestors to find the top-most participant (if one exists) WindowContainer topParent = null; tmpList.clear(); + if (reportIfNotTop(wc)) { + tmpList.add(wc); + } for (WindowContainer p = wc.getParent(); p != null; p = p.getParent()) { if (participants.contains(p)) { topParent = p; @@ -479,8 +537,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe } } if (topParent != null) { - // There was an ancestor participant, so don't add wc to targets. However, continue - // to add any always-report parents along the way. + // There was an ancestor participant, so don't add wc to targets unless always- + // report. Similarly, add any always-report parents along the way. for (int i = 0; i < tmpList.size(); ++i) { targets.add(tmpList.get(i)); final ChangeInfo info = changes.get(tmpList.get(i)); @@ -508,10 +566,70 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe while (tryPromote(topTargets, targets, changes)) { // Empty on purpose } + return targets; + } - // Convert all the resolved ChangeInfos into a TransactionInfo object. - for (int i = targets.size() - 1; i >= 0; --i) { - final WindowContainer target = targets.valueAt(i); + /** Add any of `members` within `root` to `out` in top-to-bottom z-order. */ + private static void addMembersInOrder(WindowContainer root, ArraySet<WindowContainer> members, + ArrayList<WindowContainer> out) { + for (int i = root.getChildCount() - 1; i >= 0; --i) { + final WindowContainer child = root.getChildAt(i); + addMembersInOrder(child, members, out); + if (members.contains(child)) { + out.add(child); + } + } + } + + /** + * Construct a TransitionInfo object from a set of targets and changes. Also populates the + * root surface. + */ + @VisibleForTesting + @NonNull + static TransitionInfo calculateTransitionInfo(int type, ArraySet<WindowContainer> targets, + ArrayMap<WindowContainer, ChangeInfo> changes) { + final TransitionInfo out = new TransitionInfo(type); + if (targets.isEmpty()) { + out.setRootLeash(new SurfaceControl(), 0, 0); + return out; + } + + // Find the top-most shared ancestor + WindowContainer ancestor = targets.valueAt(0).getParent(); + // Go up ancestor parent chain until all topTargets are descendants. + ancestorLoop: + while (ancestor != null) { + for (int i = 1; i < targets.size(); ++i) { + if (!targets.valueAt(i).isDescendantOf(ancestor)) { + ancestor = ancestor.getParent(); + continue ancestorLoop; + } + } + break; + } + + // Sort targets top-to-bottom in Z. + ArrayList<WindowContainer> sortedTargets = new ArrayList<>(); + addMembersInOrder(ancestor, targets, sortedTargets); + + // make leash based on highest (z-order) direct child of ancestor with a participant. + WindowContainer leashReference = sortedTargets.get(0); + while (leashReference.getParent() != ancestor) { + leashReference = leashReference.getParent(); + } + final SurfaceControl rootLeash = leashReference.makeAnimationLeash().setName( + "Transition Root: " + leashReference.getName()).build(); + SurfaceControl.Transaction t = ancestor.mWmService.mTransactionFactory.get(); + t.setLayer(rootLeash, leashReference.getLastLayer()); + t.apply(); + t.close(); + out.setRootLeash(rootLeash, ancestor.getBounds().left, ancestor.getBounds().top); + + // Convert all the resolved ChangeInfos into TransactionInfo.Change objects in order. + final int count = sortedTargets.size(); + for (int i = 0; i < count; ++i) { + final WindowContainer target = sortedTargets.get(i); final ChangeInfo info = changes.get(target); final TransitionInfo.Change change = new TransitionInfo.Change( target.mRemoteToken != null ? target.mRemoteToken.toWindowContainerToken() @@ -520,8 +638,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe change.setParent(info.mParent.mRemoteToken.toWindowContainerToken()); } change.setMode(info.getTransitMode(target)); - change.setStartBounds(info.mAbsoluteBounds); - change.setEndBounds(target.getBounds()); + change.setStartAbsBounds(info.mAbsoluteBounds); + change.setEndAbsBounds(target.getBounds()); + change.setEndRelOffset(target.getBounds().left - target.getParent().getBounds().left, + target.getBounds().top - target.getParent().getBounds().top); out.addChange(change); } @@ -543,23 +663,26 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe // before change state boolean mVisible; int mWindowingMode; - Rect mAbsoluteBounds; + final Rect mAbsoluteBounds = new Rect(); ChangeInfo(@NonNull WindowContainer origState) { mVisible = origState.isVisibleRequested(); mWindowingMode = origState.getWindowingMode(); - mAbsoluteBounds = origState.getBounds(); + mAbsoluteBounds.set(origState.getBounds()); } @VisibleForTesting ChangeInfo(boolean visible, boolean existChange) { mVisible = visible; - mAbsoluteBounds = new Rect(); mExistenceChanged = existChange; } boolean hasChanged(@NonNull WindowContainer newState) { - return newState.isVisibleRequested() != mVisible + // If it's invisible and hasn't changed visibility, always return false since even if + // something changed, it wouldn't be a visible change. + final boolean currVisible = newState.isVisibleRequested(); + if (currVisible == mVisible && !mVisible) return false; + return currVisible != mVisible // if mWindowingMode is 0, this container wasn't attached at collect time, so // assume no change in windowing-mode. || (mWindowingMode != 0 && newState.getWindowingMode() != mWindowingMode) diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 890ae8f2a434..2f5d10afe3da 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -109,10 +109,18 @@ class TransitionController { return mCollectingTransition != null; } + /** + * @return {@code true} if transition is actively playing. This is not necessarily {@code true} + * during collection. + */ + boolean isPlaying() { + return !mPlayingTransitions.isEmpty(); + } + /** @return {@code true} if a transition is running */ boolean inTransition() { // TODO(shell-transitions): eventually properly support multiple - return mCollectingTransition != null || !mPlayingTransitions.isEmpty(); + return isCollecting() || isPlaying(); } /** @return {@code true} if wc is in a participant subtree */ diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 06449c69f1be..a1bb89d26f2f 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2089,6 +2089,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } void assignLayer(Transaction t, int layer) { + // Don't assign layers while a transition animation is playing + // TODO(b/173528115): establish robust best-practices around z-order fighting. + if (mWmService.mAtmService.getTransitionController().isPlaying()) return; final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null; if (mSurfaceControl != null && changed) { setLayer(t, layer); @@ -2113,6 +2116,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< mSurfaceAnimator.setLayer(t, layer); } + int getLastLayer() { + return mLastLayer; + } + protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) { // Route through surface animator to accommodate that our surface control might be diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index d082778f50ba..a3a9eb773abf 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -30,6 +30,7 @@ import android.view.IWindow; import android.view.InputChannel; import android.view.MagnificationSpec; import android.view.WindowInfo; +import android.view.WindowManager.DisplayImePolicy; import com.android.internal.policy.KeyInterceptionInfo; import com.android.server.input.InputManagerService; @@ -506,12 +507,12 @@ public abstract class WindowManagerInternal { public abstract boolean shouldShowSystemDecorOnDisplay(int displayId); /** - * Indicates that the display should show IME. + * Indicates the policy for how the display should show IME. * * @param displayId The id of the display. - * @return {@code true} if the display should show IME when an input field become focused on it. + * @return The policy for how the display should show IME. */ - public abstract boolean shouldShowIme(int displayId); + public abstract @DisplayImePolicy int getDisplayImePolicy(int displayId); /** * Show IME on imeTargetWindow once IME has finished layout. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 580c088ec133..d62df85e3cc0 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -48,6 +48,7 @@ import static android.provider.Settings.Global.DEVELOPMENT_IGNORE_VENDOR_DISPLAY import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; @@ -255,6 +256,7 @@ import android.view.View; import android.view.WindowContentFrameStats; import android.view.WindowInsets; import android.view.WindowManager; +import android.view.WindowManager.DisplayImePolicy; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.RemoveContentMode; import android.view.WindowManagerGlobal; @@ -1625,7 +1627,7 @@ public class WindowManagerService extends IWindowManager.Stub } final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy(); - displayPolicy.adjustWindowParamsLw(win, win.mAttrs, callingPid, callingUid); + displayPolicy.adjustWindowParamsLw(win, win.mAttrs); win.updateRequestedVisibility(requestedVisibility); res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid); @@ -2195,7 +2197,7 @@ public class WindowManagerService extends IWindowManager.Stub int flagChanges = 0; int privateFlagChanges = 0; if (attrs != null) { - displayPolicy.adjustWindowParamsLw(win, attrs, pid, uid); + displayPolicy.adjustWindowParamsLw(win, attrs); win.mToken.adjustWindowParams(win, attrs); int disableFlags = (attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility) & DISABLE_MASK; @@ -7245,28 +7247,25 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public boolean shouldShowIme(int displayId) { - if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowIme()")) { + public @DisplayImePolicy int getDisplayImePolicy(int displayId) { + if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getDisplayImePolicy()")) { throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); } - boolean show; final DisplayContent dc = mRoot.getDisplayContent(displayId); if (dc == null) { ProtoLog.w(WM_ERROR, - "Attempted to get IME flag of a display that does not exist: %d", + "Attempted to get IME policy of a display that does not exist: %d", displayId); - return false; + return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; } synchronized (mGlobalLock) { - show = dc.canShowIme(); + return dc.getImePolicy(); } - - return show; } @Override - public void setShouldShowIme(int displayId, boolean shouldShow) { - if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setShouldShowIme()")) { + public void setDisplayImePolicy(int displayId, @DisplayImePolicy int imePolicy) { + if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setDisplayImePolicy()")) { throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission"); } final long origId = Binder.clearCallingIdentity(); @@ -7274,16 +7273,16 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mGlobalLock) { final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null); if (displayContent == null) { - ProtoLog.w(WM_ERROR, "Attempted to set IME flag to a display that does not " - + "exist: %d", displayId); + ProtoLog.w(WM_ERROR, "Attempted to set IME policy to a display" + + " that does not exist: %d", displayId); return; } if (!displayContent.isTrusted()) { - throw new SecurityException("Attempted to set IME flag to an untrusted " + throw new SecurityException("Attempted to set IME policy to an untrusted " + "virtual display: " + displayId); } - mDisplayWindowSettings.setShouldShowImeLocked(displayContent, shouldShow); + mDisplayWindowSettings.setDisplayImePolicy(displayContent, imePolicy); displayContent.reconfigureDisplayLocked(); } @@ -7765,9 +7764,9 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public boolean shouldShowIme(int displayId) { + public @DisplayImePolicy int getDisplayImePolicy(int displayId) { synchronized (mGlobalLock) { - return WindowManagerService.this.shouldShowIme(displayId); + return WindowManagerService.this.getDisplayImePolicy(displayId); } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index c55f059cae16..8f8fea34e620 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -730,6 +730,28 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return mHasActivities || mHasRecentTasks; } + @Nullable + TaskDisplayArea getTopActivityDisplayArea() { + if (mActivities.isEmpty()) { + return null; + } + + final int lastIndex = mActivities.size() - 1; + ActivityRecord topRecord = mActivities.get(lastIndex); + TaskDisplayArea displayArea = topRecord.getDisplayArea(); + + for (int index = lastIndex - 1; index >= 0; --index) { + ActivityRecord nextRecord = mActivities.get(index); + TaskDisplayArea nextDisplayArea = nextRecord.getDisplayArea(); + if (nextRecord.compareTo(topRecord) > 0 && nextDisplayArea != null) { + topRecord = nextRecord; + displayArea = nextDisplayArea; + } + } + + return displayArea; + } + private boolean hasActivityInVisibleTask() { for (int i = mActivities.size() - 1; i >= 0; --i) { Task task = mActivities.get(i).getTask(); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index e99c7f92a890..c318fad4d0a0 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5271,6 +5271,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mSurfaceControl == null) { return; } + if (mWmService.mWindowPlacerLocked.isLayoutDeferred() || isGoneForLayout()) { + // Since this relies on mWindowFrames, changes made while layout is deferred are + // likely to be invalid. Similarly, if it's goneForLayout, mWindowFrames may not be + // up-to-date and thus can't be relied on. + return; + } transformFrameToSurfacePosition(mWindowFrames.mFrame.left, mWindowFrames.mFrame.top, mSurfacePosition); diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index da2c005d7332..6da9517743d2 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -53,8 +53,8 @@ cc_library_static { "com_android_server_UsbDescriptorParser.cpp", "com_android_server_UsbMidiDevice.cpp", "com_android_server_UsbHostManager.cpp", + "com_android_server_vibrator_VibratorController.cpp", "com_android_server_VibratorManagerService.cpp", - "com_android_server_VibratorService.cpp", "com_android_server_PersistentDataBlockService.cpp", "com_android_server_am_CachedAppOptimizer.cpp", "com_android_server_am_LowMemDetector.cpp", diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS index 4c017f5513a2..6f74885b98e5 100644 --- a/services/core/jni/OWNERS +++ b/services/core/jni/OWNERS @@ -2,8 +2,8 @@ per-file com_android_server_lights_LightsService.cpp = michaelwr@google.com, santoscordon@google.com # Haptics +per-file com_android_server_vibrator_VibratorController.cpp = michaelwr@google.com per-file com_android_server_VibratorManagerService.cpp = michaelwr@google.com -per-file com_android_server_VibratorService.cpp = michaelwr@google.com # Input per-file com_android_server_input_InputManagerService.cpp = michaelwr@google.com, svv@google.com diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index 9aca84849fc6..afce5379febb 100644 --- a/services/core/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,20 +14,18 @@ * limitations under the License. */ -#define LOG_TAG "VibratorService" +#define LOG_TAG "VibratorController" #include <android/hardware/vibrator/1.3/IVibrator.h> #include <android/hardware/vibrator/IVibrator.h> -#include "jni.h" #include <nativehelper/JNIHelp.h> #include "android_runtime/AndroidRuntime.h" #include "core_jni_helpers.h" +#include "jni.h" -#include <utils/misc.h> #include <utils/Log.h> - -#include <inttypes.h> +#include <utils/misc.h> #include <vibratorservice/VibratorHalController.h> @@ -48,58 +46,59 @@ static struct { } sPrimitiveClassInfo; static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) == - static_cast<uint8_t>(aidl::EffectStrength::LIGHT)); + static_cast<uint8_t>(aidl::EffectStrength::LIGHT)); static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) == - static_cast<uint8_t>(aidl::EffectStrength::MEDIUM)); + static_cast<uint8_t>(aidl::EffectStrength::MEDIUM)); static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) == - static_cast<uint8_t>(aidl::EffectStrength::STRONG)); + static_cast<uint8_t>(aidl::EffectStrength::STRONG)); static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) == - static_cast<uint8_t>(aidl::Effect::CLICK)); + static_cast<uint8_t>(aidl::Effect::CLICK)); static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) == - static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK)); -static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == - static_cast<uint8_t>(aidl::Effect::TICK)); -static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == - static_cast<uint8_t>(aidl::Effect::THUD)); -static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == - static_cast<uint8_t>(aidl::Effect::POP)); + static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK)); +static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == static_cast<uint8_t>(aidl::Effect::TICK)); +static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == static_cast<uint8_t>(aidl::Effect::THUD)); +static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == static_cast<uint8_t>(aidl::Effect::POP)); static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) == - static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK)); + static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK)); static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_1)); + static_cast<uint8_t>(aidl::Effect::RINGTONE_1)); static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_2)); + static_cast<uint8_t>(aidl::Effect::RINGTONE_2)); static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == - static_cast<uint8_t>(aidl::Effect::RINGTONE_15)); + static_cast<uint8_t>(aidl::Effect::RINGTONE_15)); static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == - static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); + static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); -class NativeVibratorService { +class VibratorControllerWrapper { public: - NativeVibratorService(JNIEnv* env, jobject callbackListener) - : mController(std::make_unique<vibrator::HalController>()), + VibratorControllerWrapper(JNIEnv* env, int32_t vibratorId, jobject callbackListener) + // TODO(b/167946816): use ManagerHalController to get vibrator by id + : mHal(std::make_unique<vibrator::HalController>()), + mVibratorId(vibratorId), mCallbackListener(env->NewGlobalRef(callbackListener)) { LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr, "Unable to create global reference to vibration callback handler"); } - ~NativeVibratorService() { + ~VibratorControllerWrapper() { auto jniEnv = GetOrAttachJNIEnvironment(sJvm); jniEnv->DeleteGlobalRef(mCallbackListener); } - vibrator::HalController* controller() const { return mController.get(); } + vibrator::HalController* hal() const { return mHal.get(); } std::function<void()> createCallback(jlong vibrationId) { return [vibrationId, this]() { auto jniEnv = GetOrAttachJNIEnvironment(sJvm); - jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, vibrationId); + jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, mVibratorId, + vibrationId); }; } private: - const std::unique_ptr<vibrator::HalController> mController; + const std::unique_ptr<vibrator::HalController> mHal; + const int32_t mVibratorId; const jobject mCallbackListener; }; @@ -112,80 +111,80 @@ static aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primit return effect; } -static void destroyNativeService(void* servicePtr) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service) { - delete service; +static void destroyNativeWrapper(void* ptr) { + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper) { + delete wrapper; } } -static jlong vibratorInit(JNIEnv* env, jclass /* clazz */, jobject callbackListener) { - std::unique_ptr<NativeVibratorService> service = - std::make_unique<NativeVibratorService>(env, callbackListener); - service->controller()->init(); - return reinterpret_cast<jlong>(service.release()); +static jlong vibratorInit(JNIEnv* env, jclass /* clazz */, jint vibratorId, + jobject callbackListener) { + std::unique_ptr<VibratorControllerWrapper> wrapper = + std::make_unique<VibratorControllerWrapper>(env, vibratorId, callbackListener); + wrapper->hal()->init(); + return reinterpret_cast<jlong>(wrapper.release()); } static jlong vibratorGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) { - return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeService)); + return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeWrapper)); } -static jboolean vibratorExists(JNIEnv* env, jclass /* clazz */, jlong servicePtr) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorExists failed because native service was not initialized"); +static jboolean vibratorIsAvailable(JNIEnv* env, jclass /* clazz */, jlong ptr) { + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorIsAvailable failed because native wrapper was not initialized"); return JNI_FALSE; } - return service->controller()->ping().isOk() ? JNI_TRUE : JNI_FALSE; + return wrapper->hal()->ping().isOk() ? JNI_TRUE : JNI_FALSE; } -static void vibratorOn(JNIEnv* env, jclass /* clazz */, jlong servicePtr, jlong timeoutMs, +static void vibratorOn(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong timeoutMs, jlong vibrationId) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorOn failed because native service was not initialized"); + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorOn failed because native wrapper was not initialized"); return; } - auto callback = service->createCallback(vibrationId); - service->controller()->on(std::chrono::milliseconds(timeoutMs), callback); + auto callback = wrapper->createCallback(vibrationId); + wrapper->hal()->on(std::chrono::milliseconds(timeoutMs), callback); } -static void vibratorOff(JNIEnv* env, jclass /* clazz */, jlong servicePtr) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorOff failed because native service was not initialized"); +static void vibratorOff(JNIEnv* env, jclass /* clazz */, jlong ptr) { + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorOff failed because native wrapper was not initialized"); return; } - service->controller()->off(); + wrapper->hal()->off(); } -static void vibratorSetAmplitude(JNIEnv* env, jclass /* clazz */, jlong servicePtr, - jint amplitude) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorSetAmplitude failed because native service was not initialized"); +static void vibratorSetAmplitude(JNIEnv* env, jclass /* clazz */, jlong ptr, jint amplitude) { + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorSetAmplitude failed because native wrapper was not initialized"); return; } - service->controller()->setAmplitude(static_cast<int32_t>(amplitude)); + wrapper->hal()->setAmplitude(static_cast<int32_t>(amplitude)); } -static void vibratorSetExternalControl(JNIEnv* env, jclass /* clazz */, jlong servicePtr, +static void vibratorSetExternalControl(JNIEnv* env, jclass /* clazz */, jlong ptr, jboolean enabled) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorSetExternalControl failed because native service was not initialized"); + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorSetExternalControl failed because native wrapper was not initialized"); return; } - service->controller()->setExternalControl(enabled); + wrapper->hal()->setExternalControl(enabled); } -static jintArray vibratorGetSupportedEffects(JNIEnv* env, jclass /* clazz */, jlong servicePtr) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorGetSupportedEffects failed because native service was not initialized"); +static jintArray vibratorGetSupportedEffects(JNIEnv* env, jclass /* clazz */, jlong ptr) { + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorGetSupportedEffects failed because native wrapper was not initialized"); return nullptr; } - auto result = service->controller()->getSupportedEffects(); + auto result = wrapper->hal()->getSupportedEffects(); if (!result.isOk()) { return nullptr; } @@ -196,13 +195,13 @@ static jintArray vibratorGetSupportedEffects(JNIEnv* env, jclass /* clazz */, jl return effects; } -static jintArray vibratorGetSupportedPrimitives(JNIEnv* env, jclass /* clazz */, jlong servicePtr) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorGetSupportedPrimitives failed because native service was not initialized"); +static jintArray vibratorGetSupportedPrimitives(JNIEnv* env, jclass /* clazz */, jlong ptr) { + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorGetSupportedPrimitives failed because native wrapper was not initialized"); return nullptr; } - auto result = service->controller()->getSupportedPrimitives(); + auto result = wrapper->hal()->getSupportedPrimitives(); if (!result.isOk()) { return nullptr; } @@ -213,25 +212,25 @@ static jintArray vibratorGetSupportedPrimitives(JNIEnv* env, jclass /* clazz */, return primitives; } -static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong servicePtr, jlong effect, +static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong effect, jlong strength, jlong vibrationId) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorPerformEffect failed because native service was not initialized"); + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorPerformEffect failed because native wrapper was not initialized"); return -1; } aidl::Effect effectType = static_cast<aidl::Effect>(effect); aidl::EffectStrength effectStrength = static_cast<aidl::EffectStrength>(strength); - auto callback = service->createCallback(vibrationId); - auto result = service->controller()->performEffect(effectType, effectStrength, callback); + auto callback = wrapper->createCallback(vibrationId); + auto result = wrapper->hal()->performEffect(effectType, effectStrength, callback); return result.isOk() ? result.value().count() : -1; } -static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong servicePtr, +static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, jobjectArray composition, jlong vibrationId) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorPerformComposedEffect failed because native service was not initialized"); + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorPerformComposedEffect failed because native wrapper was not initialized"); return; } size_t size = env->GetArrayLength(composition); @@ -240,46 +239,46 @@ static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong jobject element = env->GetObjectArrayElement(composition, i); effects.push_back(effectFromJavaPrimitive(env, element)); } - auto callback = service->createCallback(vibrationId); - service->controller()->performComposedEffect(effects, callback); + auto callback = wrapper->createCallback(vibrationId); + wrapper->hal()->performComposedEffect(effects, callback); } -static jlong vibratorGetCapabilities(JNIEnv* env, jclass /* clazz */, jlong servicePtr) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorGetCapabilities failed because native service was not initialized"); +static jlong vibratorGetCapabilities(JNIEnv* env, jclass /* clazz */, jlong ptr) { + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorGetCapabilities failed because native wrapper was not initialized"); return 0; } - auto result = service->controller()->getCapabilities(); + auto result = wrapper->hal()->getCapabilities(); return result.isOk() ? static_cast<jlong>(result.value()) : 0; } -static void vibratorAlwaysOnEnable(JNIEnv* env, jclass /* clazz */, jlong servicePtr, jlong id, +static void vibratorAlwaysOnEnable(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong id, jlong effect, jlong strength) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorAlwaysOnEnable failed because native service was not initialized"); + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorAlwaysOnEnable failed because native wrapper was not initialized"); return; } - service->controller()->alwaysOnEnable(static_cast<int32_t>(id), - static_cast<aidl::Effect>(effect), - static_cast<aidl::EffectStrength>(strength)); + wrapper->hal()->alwaysOnEnable(static_cast<int32_t>(id), static_cast<aidl::Effect>(effect), + static_cast<aidl::EffectStrength>(strength)); } -static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong servicePtr, jlong id) { - NativeVibratorService* service = reinterpret_cast<NativeVibratorService*>(servicePtr); - if (service == nullptr) { - ALOGE("vibratorAlwaysOnDisable failed because native service was not initialized"); +static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong id) { + VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr); + if (wrapper == nullptr) { + ALOGE("vibratorAlwaysOnDisable failed because native wrapper was not initialized"); return; } - service->controller()->alwaysOnDisable(static_cast<int32_t>(id)); + wrapper->hal()->alwaysOnDisable(static_cast<int32_t>(id)); } static const JNINativeMethod method_table[] = { - {"vibratorInit", "(Lcom/android/server/VibratorService$OnCompleteListener;)J", + {"vibratorInit", + "(ILcom/android/server/vibrator/VibratorController$OnVibrationCompleteListener;)J", (void*)vibratorInit}, {"vibratorGetFinalizer", "()J", (void*)vibratorGetFinalizer}, - {"vibratorExists", "(J)Z", (void*)vibratorExists}, + {"vibratorIsAvailable", "(J)Z", (void*)vibratorIsAvailable}, {"vibratorOn", "(JJJ)V", (void*)vibratorOn}, {"vibratorOff", "(J)V", (void*)vibratorOff}, {"vibratorSetAmplitude", "(JI)V", (void*)vibratorSetAmplitude}, @@ -295,11 +294,12 @@ static const JNINativeMethod method_table[] = { {"vibratorAlwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable}, }; -int register_android_server_VibratorService(JavaVM* jvm, JNIEnv* env) { +int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env) { sJvm = jvm; - jclass listenerClass = - FindClassOrDie(env, "com/android/server/VibratorService$OnCompleteListener"); - sMethodIdOnComplete = GetMethodIDOrDie(env, listenerClass, "onComplete", "(J)V"); + auto listenerClassName = + "com/android/server/vibrator/VibratorController$OnVibrationCompleteListener"; + jclass listenerClass = FindClassOrDie(env, listenerClassName); + sMethodIdOnComplete = GetMethodIDOrDie(env, listenerClass, "onComplete", "(IJ)V"); jclass primitiveClass = FindClassOrDie(env, "android/os/VibrationEffect$Composition$PrimitiveEffect"); @@ -307,8 +307,8 @@ int register_android_server_VibratorService(JavaVM* jvm, JNIEnv* env) { sPrimitiveClassInfo.scale = GetFieldIDOrDie(env, primitiveClass, "scale", "F"); sPrimitiveClassInfo.delay = GetFieldIDOrDie(env, primitiveClass, "delay", "I"); - return jniRegisterNativeMethods(env, "com/android/server/VibratorService", method_table, - NELEM(method_table)); + return jniRegisterNativeMethods(env, "com/android/server/vibrator/VibratorController", + method_table, NELEM(method_table)); } }; // namespace android diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 79b5fed3e448..5a0d08aeb6b3 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -37,8 +37,8 @@ int register_android_server_UsbDeviceManager(JNIEnv* env); int register_android_server_UsbMidiDevice(JNIEnv* env); int register_android_server_UsbHostManager(JNIEnv* env); int register_android_server_vr_VrManagerService(JNIEnv* env); +int register_android_server_vibrator_VibratorController(JavaVM* vm, JNIEnv* env); int register_android_server_VibratorManagerService(JNIEnv* env); -int register_android_server_VibratorService(JavaVM* vm, JNIEnv* env); int register_android_server_location_GnssLocationProvider(JNIEnv* env); int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_TestNetworkService(JNIEnv* env); @@ -90,8 +90,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_UsbAlsaJackDetector(env); register_android_server_UsbHostManager(env); register_android_server_vr_VrManagerService(env); + register_android_server_vibrator_VibratorController(vm, env); register_android_server_VibratorManagerService(env); - register_android_server_VibratorService(vm, env); register_android_server_SystemServer(env); register_android_server_location_GnssLocationProvider(env); register_android_server_connectivity_Vpn(env); diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java index 9c8f733730a7..f375421043fd 100644 --- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java @@ -16,6 +16,7 @@ package com.android.server; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyLong; @@ -44,6 +45,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.provider.DeviceConfig; import android.provider.Settings; +import android.util.ArraySet; import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.server.PackageWatchdog.PackageHealthObserverImpact; @@ -63,6 +65,7 @@ import org.mockito.stubbing.Answer; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; /** @@ -79,9 +82,11 @@ public class RescuePartyTest { private static final String PROP_DISABLE_RESCUE = "persist.sys.disable_rescue"; private static final String CALLING_PACKAGE1 = "com.package.name1"; private static final String CALLING_PACKAGE2 = "com.package.name2"; + private static final String CALLING_PACKAGE3 = "com.package.name3"; private static final String NAMESPACE1 = "namespace1"; private static final String NAMESPACE2 = "namespace2"; private static final String NAMESPACE3 = "namespace3"; + private static final String NAMESPACE4 = "namespace4"; private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG = "persist.device_config.configuration.disable_rescue_party"; private static final String PROP_DISABLE_FACTORY_RESET_FLAG = @@ -89,6 +94,8 @@ public class RescuePartyTest { private MockitoSession mSession; private HashMap<String, String> mSystemSettingsMap; + //Records the namespaces wiped by setProperties(). + private HashSet<String> mNamespacesWiped; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mMockContext; @@ -119,6 +126,7 @@ public class RescuePartyTest { .spyStatic(PackageWatchdog.class) .startMocking(); mSystemSettingsMap = new HashMap<>(); + mNamespacesWiped = new HashSet<>(); when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); // Reset observer instance to get new mock context on every run @@ -167,6 +175,16 @@ public class RescuePartyTest { anyBoolean())); doAnswer((Answer<Void>) invocationOnMock -> null) .when(() -> DeviceConfig.resetToDefaults(anyInt(), anyString())); + doAnswer((Answer<Boolean>) invocationOnMock -> { + DeviceConfig.Properties properties = invocationOnMock.getArgument(0); + String namespace = properties.getNamespace(); + // record a wipe + if (properties.getKeyset().isEmpty()) { + mNamespacesWiped.add(namespace); + } + return true; + } + ).when(() -> DeviceConfig.setProperties(any(DeviceConfig.Properties.class))); // Mock PackageWatchdog doAnswer((Answer<PackageWatchdog>) invocationOnMock -> mMockPackageWatchdog) @@ -450,6 +468,122 @@ public class RescuePartyTest { assertEquals(observer.onBootLoop(5), PackageHealthObserverImpact.USER_IMPACT_HIGH); } + @Test + public void testResetDeviceConfigForPackagesOnlyRuntimeMap() { + RescueParty.onSettingsProviderPublished(mMockContext); + verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver), + mMonitorCallbackCaptor.capture())); + + // Record DeviceConfig accesses + RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); + RemoteCallback monitorCallback = mMonitorCallbackCaptor.getValue(); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE1)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE2)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE2)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE3)); + // Fake DeviceConfig value changes + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE1)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE2)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE3)); + + doReturn("").when(() -> DeviceConfig.getString( + eq(RescueParty.NAMESPACE_CONFIGURATION), + eq(RescueParty.NAMESPACE_TO_PACKAGE_MAPPING_FLAG), + eq(""))); + + RescueParty.resetDeviceConfigForPackages(Arrays.asList(new String[]{CALLING_PACKAGE1})); + ArraySet<String> expectedNamespacesWiped = new ArraySet<String>( + Arrays.asList(new String[]{NAMESPACE1, NAMESPACE2})); + assertEquals(mNamespacesWiped, expectedNamespacesWiped); + } + + @Test + public void testResetDeviceConfigForPackagesOnlyPresetMap() { + RescueParty.onSettingsProviderPublished(mMockContext); + verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver), + mMonitorCallbackCaptor.capture())); + + String presetMapping = NAMESPACE1 + ":" + CALLING_PACKAGE1 + "," + + NAMESPACE2 + ":" + CALLING_PACKAGE2 + "," + + NAMESPACE3 + ":" + CALLING_PACKAGE1; + doReturn(presetMapping).when(() -> DeviceConfig.getString( + eq(RescueParty.NAMESPACE_CONFIGURATION), + eq(RescueParty.NAMESPACE_TO_PACKAGE_MAPPING_FLAG), + eq(""))); + + RescueParty.resetDeviceConfigForPackages(Arrays.asList(new String[]{CALLING_PACKAGE1})); + ArraySet<String> expectedNamespacesWiped = new ArraySet<String>( + Arrays.asList(new String[]{NAMESPACE1, NAMESPACE3})); + assertEquals(mNamespacesWiped, expectedNamespacesWiped); + } + + @Test + public void testResetDeviceConfigForPackagesBothMaps() { + RescueParty.onSettingsProviderPublished(mMockContext); + verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver), + mMonitorCallbackCaptor.capture())); + + // Record DeviceConfig accesses + RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); + RemoteCallback monitorCallback = mMonitorCallbackCaptor.getValue(); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE1)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE2)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE2)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE3)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE3, NAMESPACE4)); + // Fake DeviceConfig value changes + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE1)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE2)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE3)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE4)); + + String presetMapping = NAMESPACE1 + ":" + CALLING_PACKAGE1 + "," + + NAMESPACE2 + ":" + CALLING_PACKAGE2 + "," + + NAMESPACE4 + ":" + CALLING_PACKAGE3; + doReturn(presetMapping).when(() -> DeviceConfig.getString( + eq(RescueParty.NAMESPACE_CONFIGURATION), + eq(RescueParty.NAMESPACE_TO_PACKAGE_MAPPING_FLAG), + eq(""))); + + RescueParty.resetDeviceConfigForPackages( + Arrays.asList(new String[]{CALLING_PACKAGE1, CALLING_PACKAGE2})); + ArraySet<String> expectedNamespacesWiped = new ArraySet<String>( + Arrays.asList(new String[]{NAMESPACE1, NAMESPACE2, NAMESPACE3})); + assertEquals(mNamespacesWiped, expectedNamespacesWiped); + } + + @Test + public void testResetDeviceConfigNoExceptionWhenFlagMalformed() { + RescueParty.onSettingsProviderPublished(mMockContext); + verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver), + mMonitorCallbackCaptor.capture())); + + // Record DeviceConfig accesses + RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext); + RemoteCallback monitorCallback = mMonitorCallbackCaptor.getValue(); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE1)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE3)); + monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE3, NAMESPACE4)); + // Fake DeviceConfig value changes + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE1)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE2)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE3)); + monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE4)); + + String invalidPresetMapping = NAMESPACE2 + ":" + CALLING_PACKAGE2 + "," + + NAMESPACE1 + "." + CALLING_PACKAGE2; + doReturn(invalidPresetMapping).when(() -> DeviceConfig.getString( + eq(RescueParty.NAMESPACE_CONFIGURATION), + eq(RescueParty.NAMESPACE_TO_PACKAGE_MAPPING_FLAG), + eq(""))); + + RescueParty.resetDeviceConfigForPackages( + Arrays.asList(new String[]{CALLING_PACKAGE1, CALLING_PACKAGE2})); + ArraySet<String> expectedNamespacesWiped = new ArraySet<String>( + Arrays.asList(new String[]{NAMESPACE1, NAMESPACE3})); + assertEquals(mNamespacesWiped, expectedNamespacesWiped); + } + private void verifySettingsResets(int resetMode, String[] resetNamespaces, HashMap<String, Integer> configResetVerifiedTimesMap) { verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null, diff --git a/services/tests/servicestests/src/com/android/internal/location/timezone/LocationTimeZoneEventTest.java b/services/tests/servicestests/src/com/android/internal/location/timezone/LocationTimeZoneEventTest.java index 9efb38a75f35..84b886eb4b3d 100644 --- a/services/tests/servicestests/src/com/android/internal/location/timezone/LocationTimeZoneEventTest.java +++ b/services/tests/servicestests/src/com/android/internal/location/timezone/LocationTimeZoneEventTest.java @@ -29,7 +29,7 @@ import java.util.List; public class LocationTimeZoneEventTest { - private static final long ARBITRARY_ELAPSED_REALTIME_NANOS = 9999; + private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 9999; private static final List<String> ARBITRARY_TIME_ZONE_IDS = singletonList("Europe/London"); @@ -42,7 +42,7 @@ public class LocationTimeZoneEventTest { public void testBuildUnsetEventType() { new LocationTimeZoneEvent.Builder() .setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS) - .setElapsedRealtimeNanos(ARBITRARY_ELAPSED_REALTIME_NANOS) + .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS) .build(); } @@ -51,7 +51,7 @@ public class LocationTimeZoneEventTest { new LocationTimeZoneEvent.Builder() .setEventType(LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN) .setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS) - .setElapsedRealtimeNanos(ARBITRARY_ELAPSED_REALTIME_NANOS) + .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS) .build(); } @@ -59,7 +59,7 @@ public class LocationTimeZoneEventTest { public void testEquals() { LocationTimeZoneEvent.Builder builder1 = new LocationTimeZoneEvent.Builder() .setEventType(LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN) - .setElapsedRealtimeNanos(ARBITRARY_ELAPSED_REALTIME_NANOS); + .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS); { LocationTimeZoneEvent one = builder1.build(); assertEquals(one, one); @@ -67,7 +67,7 @@ public class LocationTimeZoneEventTest { LocationTimeZoneEvent.Builder builder2 = new LocationTimeZoneEvent.Builder() .setEventType(LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN) - .setElapsedRealtimeNanos(ARBITRARY_ELAPSED_REALTIME_NANOS); + .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS); { LocationTimeZoneEvent one = builder1.build(); LocationTimeZoneEvent two = builder2.build(); @@ -75,7 +75,7 @@ public class LocationTimeZoneEventTest { assertEquals(two, one); } - builder1.setElapsedRealtimeNanos(ARBITRARY_ELAPSED_REALTIME_NANOS + 1); + builder1.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS + 1); { LocationTimeZoneEvent one = builder1.build(); LocationTimeZoneEvent two = builder2.build(); @@ -83,7 +83,7 @@ public class LocationTimeZoneEventTest { assertNotEquals(two, one); } - builder2.setElapsedRealtimeNanos(ARBITRARY_ELAPSED_REALTIME_NANOS + 1); + builder2.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS + 1); { LocationTimeZoneEvent one = builder1.build(); LocationTimeZoneEvent two = builder2.build(); @@ -128,7 +128,7 @@ public class LocationTimeZoneEventTest { public void testParcelable() { LocationTimeZoneEvent.Builder builder = new LocationTimeZoneEvent.Builder() .setEventType(LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE) - .setElapsedRealtimeNanos(ARBITRARY_ELAPSED_REALTIME_NANOS); + .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS); assertRoundTripParcelable(builder.build()); builder.setEventType(LocationTimeZoneEvent.EVENT_TYPE_SUCCESS) diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java index 6152421db659..64f31358ccb3 100644 --- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java @@ -43,6 +43,8 @@ import android.content.ContentResolver; import android.content.Context; import android.content.ContextWrapper; import android.content.pm.PackageManagerInternal; +import android.hardware.input.IInputManager; +import android.hardware.input.InputManager; import android.hardware.vibrator.IVibrator; import android.media.AudioAttributes; import android.media.AudioManager; @@ -63,11 +65,13 @@ import android.os.Vibrator; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; import android.provider.Settings; +import android.view.InputDevice; import androidx.test.InstrumentationRegistry; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; +import com.android.server.vibrator.VibratorController; import org.junit.After; import org.junit.Before; @@ -118,8 +122,9 @@ public class VibratorServiceTest { // TODO(b/131311651): replace with a FakeVibrator instead. @Mock private Vibrator mVibratorMock; @Mock private AppOpsManager mAppOpsManagerMock; - @Mock private VibratorService.NativeWrapper mNativeWrapperMock; + @Mock private VibratorController.NativeWrapper mNativeWrapperMock; @Mock private IVibratorStateListener mVibratorStateListenerMock; + @Mock private IInputManager mIInputManagerMock; @Mock private IBinder mVibratorStateListenerBinderMock; private TestLooper mTestLooper; @@ -129,10 +134,12 @@ public class VibratorServiceTest { public void setUp() throws Exception { mTestLooper = new TestLooper(); mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); + InputManager inputManager = InputManager.resetInstance(mIInputManagerMock); ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy); when(mContextSpy.getContentResolver()).thenReturn(contentResolver); when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibratorMock); + when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager); when(mContextSpy.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManagerMock); when(mVibratorMock.getDefaultHapticFeedbackIntensity()) .thenReturn(Vibrator.VIBRATION_INTENSITY_MEDIUM); @@ -145,6 +152,7 @@ public class VibratorServiceTest { .thenReturn(new ComponentName("", "")); when(mPowerManagerInternalMock.getLowPowerState(PowerManager.ServiceType.VIBRATION)) .thenReturn(mPowerSaveStateMock); + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]); setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, @@ -168,8 +176,9 @@ public class VibratorServiceTest { VibratorService service = new VibratorService(mContextSpy, new VibratorService.Injector() { @Override - VibratorService.NativeWrapper getNativeWrapper() { - return mNativeWrapperMock; + VibratorController createVibratorController( + VibratorController.OnVibrationCompleteListener listener) { + return new VibratorController(0, listener, mNativeWrapperMock); } @Override @@ -189,19 +198,19 @@ public class VibratorServiceTest { @Test public void createService_initializesNativeService() { createService(); - verify(mNativeWrapperMock).vibratorInit(notNull()); - verify(mNativeWrapperMock).vibratorOff(); + verify(mNativeWrapperMock).init(eq(0), notNull()); + verify(mNativeWrapperMock).off(); } @Test public void hasVibrator_withVibratorHalPresent_returnsTrue() { - when(mNativeWrapperMock.vibratorExists()).thenReturn(true); + when(mNativeWrapperMock.isAvailable()).thenReturn(true); assertTrue(createService().hasVibrator()); } @Test public void hasVibrator_withNoVibratorHalPresent_returnsFalse() { - when(mNativeWrapperMock.vibratorExists()).thenReturn(false); + when(mNativeWrapperMock.isAvailable()).thenReturn(false); assertFalse(createService().hasVibrator()); } @@ -217,8 +226,17 @@ public class VibratorServiceTest { } @Test + public void hasAmplitudeControl_withInputDevices_returnsTrue() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(1)).thenReturn(createInputDeviceWithVibrator(1)); + mockVibratorCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1); + assertTrue(createService().hasAmplitudeControl()); + } + + @Test public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() { - when(mNativeWrapperMock.vibratorGetSupportedEffects()).thenReturn(null); + when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null); assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN}, createService().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK})); } @@ -227,7 +245,7 @@ public class VibratorServiceTest { public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() { int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK}; - when(mNativeWrapperMock.vibratorGetSupportedEffects()) + when(mNativeWrapperMock.getSupportedEffects()) .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); assertArrayEquals( new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES, @@ -247,7 +265,7 @@ public class VibratorServiceTest { @Test public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() { mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - when(mNativeWrapperMock.vibratorGetSupportedPrimitives()).thenReturn(null); + when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null); assertArrayEquals(new boolean[]{false, false}, createService().arePrimitivesSupported(new int[]{ @@ -259,7 +277,7 @@ public class VibratorServiceTest { @Test public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() { mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - when(mNativeWrapperMock.vibratorGetSupportedPrimitives()) + when(mNativeWrapperMock.getSupportedPrimitives()) .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); assertArrayEquals(new boolean[]{true, false}, @@ -275,7 +293,7 @@ public class VibratorServiceTest { assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS)); - verify(mNativeWrapperMock).vibratorAlwaysOnEnable( + verify(mNativeWrapperMock).alwaysOnEnable( eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); } @@ -286,8 +304,8 @@ public class VibratorServiceTest { assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, VibrationEffect.createOneShot(100, 255), ALARM_ATTRS)); - verify(mNativeWrapperMock, never()).vibratorAlwaysOnDisable(anyLong()); - verify(mNativeWrapperMock, never()).vibratorAlwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong()); + verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); } @Test @@ -295,15 +313,15 @@ public class VibratorServiceTest { mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, null, ALARM_ATTRS)); - verify(mNativeWrapperMock).vibratorAlwaysOnDisable(eq(1L)); + verify(mNativeWrapperMock).alwaysOnDisable(eq(1L)); } @Test public void setAlwaysOnEffect_withoutCapability_ignoresEffect() { assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS)); - verify(mNativeWrapperMock, never()).vibratorAlwaysOnDisable(anyLong()); - verify(mNativeWrapperMock, never()).vibratorAlwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong()); + verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); } @Test @@ -322,9 +340,9 @@ public class VibratorServiceTest { vibrate(createService(), VibrationEffect.createOneShot(100, 100), RINGTONE_ATTRS); InOrder inOrderVerifier = inOrder(mNativeWrapperMock); - inOrderVerifier.verify(mNativeWrapperMock, never()).vibratorOn(eq(1L), anyLong()); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(10L), anyLong()); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(100L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock, never()).on(eq(1L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(10L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(100L), anyLong()); } @Test @@ -375,6 +393,22 @@ public class VibratorServiceTest { } @Test + public void vibrate_withOneShotAndInputDevices_vibratesInputDevices() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(1)).thenReturn(createInputDeviceWithVibrator(1)); + setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1); + VibratorService service = createService(); + Mockito.clearInvocations(mNativeWrapperMock); + + VibrationEffect effect = VibrationEffect.createOneShot(100, 128); + vibrate(service, effect); + assertFalse(service.isVibrating()); + + verify(mIInputManagerMock).vibrate(eq(1), eq(effect), any()); + verify(mNativeWrapperMock, never()).on(anyLong(), anyLong()); + } + + @Test public void vibrate_withOneShotAndAmplitudeControl_turnsVibratorOnAndSetsAmplitude() { mockVibratorCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); VibratorService service = createService(); @@ -383,9 +417,9 @@ public class VibratorServiceTest { vibrate(service, VibrationEffect.createOneShot(100, 128)); assertTrue(service.isVibrating()); - verify(mNativeWrapperMock).vibratorOff(); - verify(mNativeWrapperMock).vibratorOn(eq(100L), gt(0L)); - verify(mNativeWrapperMock).vibratorSetAmplitude(eq(128)); + verify(mNativeWrapperMock).off(); + verify(mNativeWrapperMock).on(eq(100L), gt(0L)); + verify(mNativeWrapperMock).setAmplitude(eq(128)); } @Test @@ -396,26 +430,45 @@ public class VibratorServiceTest { vibrate(service, VibrationEffect.createOneShot(100, 128)); assertTrue(service.isVibrating()); - verify(mNativeWrapperMock).vibratorOff(); - verify(mNativeWrapperMock).vibratorOn(eq(100L), gt(0L)); - verify(mNativeWrapperMock, never()).vibratorSetAmplitude(anyInt()); + verify(mNativeWrapperMock).off(); + verify(mNativeWrapperMock).on(eq(100L), gt(0L)); + verify(mNativeWrapperMock, never()).setAmplitude(anyInt()); } @Test public void vibrate_withPrebaked_performsEffect() { - when(mNativeWrapperMock.vibratorGetSupportedEffects()) + when(mNativeWrapperMock.getSupportedEffects()) .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); VibratorService service = createService(); Mockito.clearInvocations(mNativeWrapperMock); vibrate(service, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)); - verify(mNativeWrapperMock).vibratorOff(); - verify(mNativeWrapperMock).vibratorPerformEffect(eq((long) VibrationEffect.EFFECT_CLICK), + verify(mNativeWrapperMock).off(); + verify(mNativeWrapperMock).perform(eq((long) VibrationEffect.EFFECT_CLICK), eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), gt(0L)); } @Test + public void vibrate_withPrebakedAndInputDevices_vibratesFallbackWaveformOnInputDevices() + throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(1)).thenReturn(createInputDeviceWithVibrator(1)); + setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1); + VibratorService service = createService(); + Mockito.clearInvocations(mNativeWrapperMock); + + vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK)); + assertFalse(service.isVibrating()); + + // Wait for VibrateThread to turn input device vibrator ON. + Thread.sleep(5); + verify(mIInputManagerMock).vibrate(eq(1), any(), any()); + verify(mNativeWrapperMock, never()).on(anyLong(), anyLong()); + verify(mNativeWrapperMock, never()).perform(anyLong(), anyLong(), anyLong()); + } + + @Test public void vibrate_withComposed_performsEffect() { mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); VibratorService service = createService(); @@ -429,9 +482,8 @@ public class VibratorServiceTest { ArgumentCaptor<VibrationEffect.Composition.PrimitiveEffect[]> primitivesCaptor = ArgumentCaptor.forClass(VibrationEffect.Composition.PrimitiveEffect[].class); - verify(mNativeWrapperMock).vibratorOff(); - verify(mNativeWrapperMock).vibratorPerformComposedEffect( - primitivesCaptor.capture(), gt(0L)); + verify(mNativeWrapperMock).off(); + verify(mNativeWrapperMock).compose(primitivesCaptor.capture(), gt(0L)); // Check all primitive effect fields are passed down to the HAL. assertEquals(1, primitivesCaptor.getValue().length); @@ -442,6 +494,27 @@ public class VibratorServiceTest { } @Test + public void vibrate_withComposedAndInputDevices_vibratesInputDevices() + throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1, 2}); + when(mIInputManagerMock.getInputDevice(1)).thenReturn(createInputDeviceWithVibrator(1)); + when(mIInputManagerMock.getInputDevice(2)).thenReturn(createInputDeviceWithVibrator(2)); + setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1); + VibratorService service = createService(); + Mockito.clearInvocations(mNativeWrapperMock); + + VibrationEffect effect = VibrationEffect.startComposition() + .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 10) + .compose(); + vibrate(service, effect); + assertFalse(service.isVibrating()); + + verify(mIInputManagerMock).vibrate(eq(1), eq(effect), any()); + verify(mIInputManagerMock).vibrate(eq(2), eq(effect), any()); + verify(mNativeWrapperMock, never()).compose(any(), anyLong()); + } + + @Test public void vibrate_withWaveform_controlsVibratorAmplitudeDuringTotalVibrationTime() throws Exception { mockVibratorCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); @@ -455,12 +528,12 @@ public class VibratorServiceTest { // Wait for VibrateThread to finish: 10ms 100, 10ms 200, 10ms 50. Thread.sleep(40); InOrder inOrderVerifier = inOrder(mNativeWrapperMock); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(30L), anyLong()); - inOrderVerifier.verify(mNativeWrapperMock).vibratorSetAmplitude(eq(100)); - inOrderVerifier.verify(mNativeWrapperMock).vibratorSetAmplitude(eq(200)); - inOrderVerifier.verify(mNativeWrapperMock).vibratorSetAmplitude(eq(50)); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); + inOrderVerifier.verify(mNativeWrapperMock).off(); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(30L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).setAmplitude(eq(100)); + inOrderVerifier.verify(mNativeWrapperMock).setAmplitude(eq(200)); + inOrderVerifier.verify(mNativeWrapperMock).setAmplitude(eq(50)); + inOrderVerifier.verify(mNativeWrapperMock).off(); } @Test @@ -473,12 +546,12 @@ public class VibratorServiceTest { doAnswer(invocation -> { Thread.currentThread().sleep(stepDuration / 4); return null; - }).when(mNativeWrapperMock).vibratorOn(anyLong(), anyLong()); + }).when(mNativeWrapperMock).on(anyLong(), anyLong()); // 25% of each waveform step will be spent on the native setAmplitude() call.. doAnswer(invocation -> { Thread.currentThread().sleep(stepDuration / 4); return null; - }).when(mNativeWrapperMock).vibratorSetAmplitude(anyInt()); + }).when(mNativeWrapperMock).setAmplitude(anyInt()); VibratorService service = createService(); @@ -500,42 +573,61 @@ public class VibratorServiceTest { } @Test + public void vibrate_withWaveformAndInputDevices_vibratesInputDevices() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(1)).thenReturn(createInputDeviceWithVibrator(1)); + setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1); + VibratorService service = createService(); + Mockito.clearInvocations(mNativeWrapperMock); + + VibrationEffect effect = VibrationEffect.createWaveform( + new long[]{10, 10, 10}, new int[]{100, 200, 50}, -1); + vibrate(service, effect); + assertFalse(service.isVibrating()); + + // Wait for VibrateThread to turn input device vibrator ON. + Thread.sleep(5); + verify(mIInputManagerMock).vibrate(eq(1), eq(effect), any()); + verify(mNativeWrapperMock, never()).on(anyLong(), anyLong()); + } + + @Test public void vibrate_withOneShotAndNativeCallbackTriggered_finishesVibration() { VibratorService service = createService(); doAnswer(invocation -> { service.onVibrationComplete(invocation.getArgument(1)); return null; - }).when(mNativeWrapperMock).vibratorOn(anyLong(), anyLong()); + }).when(mNativeWrapperMock).on(anyLong(), anyLong()); Mockito.clearInvocations(mNativeWrapperMock); vibrate(service, VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)); InOrder inOrderVerifier = inOrder(mNativeWrapperMock); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(100L), gt(0L)); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); + inOrderVerifier.verify(mNativeWrapperMock).off(); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(100L), gt(0L)); + inOrderVerifier.verify(mNativeWrapperMock).off(); } @Test public void vibrate_withPrebakedAndNativeCallbackTriggered_finishesVibration() { - when(mNativeWrapperMock.vibratorGetSupportedEffects()) + when(mNativeWrapperMock.getSupportedEffects()) .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); VibratorService service = createService(); doAnswer(invocation -> { service.onVibrationComplete(invocation.getArgument(2)); return 10_000L; // 10s - }).when(mNativeWrapperMock).vibratorPerformEffect(anyLong(), anyLong(), anyLong()); + }).when(mNativeWrapperMock).perform(anyLong(), anyLong(), anyLong()); Mockito.clearInvocations(mNativeWrapperMock); vibrate(service, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)); InOrder inOrderVerifier = inOrder(mNativeWrapperMock); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); - inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformEffect( + inOrderVerifier.verify(mNativeWrapperMock).off(); + inOrderVerifier.verify(mNativeWrapperMock).perform( eq((long) VibrationEffect.EFFECT_CLICK), eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), gt(0L)); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); + inOrderVerifier.verify(mNativeWrapperMock).off(); } @Test @@ -545,7 +637,7 @@ public class VibratorServiceTest { doAnswer(invocation -> { service.onVibrationComplete(invocation.getArgument(1)); return null; - }).when(mNativeWrapperMock).vibratorOn(anyLong(), anyLong()); + }).when(mNativeWrapperMock).on(anyLong(), anyLong()); Mockito.clearInvocations(mNativeWrapperMock); VibrationEffect effect = VibrationEffect.createWaveform(new long[]{1, 3, 1, 2}, -1); @@ -554,11 +646,11 @@ public class VibratorServiceTest { // Wait for VibrateThread to finish: 1ms OFF, 3ms ON, 1ms OFF, 2ms ON. Thread.sleep(15); InOrder inOrderVerifier = inOrder(mNativeWrapperMock); - inOrderVerifier.verify(mNativeWrapperMock, times(2)).vibratorOff(); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(3L), anyLong()); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOn(eq(2L), anyLong()); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); + inOrderVerifier.verify(mNativeWrapperMock, times(2)).off(); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(3L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).off(); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(2L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).off(); } @Test @@ -568,7 +660,7 @@ public class VibratorServiceTest { doAnswer(invocation -> { service.onVibrationComplete(invocation.getArgument(1)); return null; - }).when(mNativeWrapperMock).vibratorPerformComposedEffect(any(), anyLong()); + }).when(mNativeWrapperMock).compose(any(), anyLong()); Mockito.clearInvocations(mNativeWrapperMock); VibrationEffect effect = VibrationEffect.startComposition() @@ -577,14 +669,14 @@ public class VibratorServiceTest { vibrate(service, effect); InOrder inOrderVerifier = inOrder(mNativeWrapperMock); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); - inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformComposedEffect( + inOrderVerifier.verify(mNativeWrapperMock).off(); + inOrderVerifier.verify(mNativeWrapperMock).compose( any(VibrationEffect.Composition.PrimitiveEffect[].class), gt(0L)); - inOrderVerifier.verify(mNativeWrapperMock).vibratorOff(); + inOrderVerifier.verify(mNativeWrapperMock).off(); } @Test - public void cancelVibrate_withDeviceVibrating_callsVibratorOff() { + public void cancelVibrate_withDeviceVibrating_callsoff() { VibratorService service = createService(); vibrate(service, VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)); assertTrue(service.isVibrating()); @@ -592,7 +684,7 @@ public class VibratorServiceTest { service.cancelVibrate(service); assertFalse(service.isVibrating()); - verify(mNativeWrapperMock).vibratorOff(); + verify(mNativeWrapperMock).off(); } @Test @@ -602,24 +694,23 @@ public class VibratorServiceTest { service.cancelVibrate(service); assertFalse(service.isVibrating()); - verify(mNativeWrapperMock, never()).vibratorOff(); + verify(mNativeWrapperMock, never()).off(); } @Test public void registerVibratorStateListener_callbacksAreTriggered() throws Exception { VibratorService service = createService(); - doAnswer(invocation -> { - service.onVibrationComplete(invocation.getArgument(1)); - return null; - }).when(mNativeWrapperMock).vibratorOn(anyLong(), anyLong()); service.registerVibratorStateListener(mVibratorStateListenerMock); - verify(mVibratorStateListenerMock).onVibrating(false); - Mockito.clearInvocations(mVibratorStateListenerMock); vibrate(service, VibrationEffect.createOneShot(10, VibrationEffect.DEFAULT_AMPLITUDE)); + service.cancelVibrate(service); + InOrder inOrderVerifier = inOrder(mVibratorStateListenerMock); + // First notification done when listener is registered. + inOrderVerifier.verify(mVibratorStateListenerMock).onVibrating(false); inOrderVerifier.verify(mVibratorStateListenerMock).onVibrating(eq(true)); inOrderVerifier.verify(mVibratorStateListenerMock).onVibrating(eq(false)); + inOrderVerifier.verifyNoMoreInteractions(); } @Test @@ -659,16 +750,16 @@ public class VibratorServiceTest { vibrate(service, VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK), RINGTONE_ATTRS); - verify(mNativeWrapperMock).vibratorPerformEffect( + verify(mNativeWrapperMock).perform( eq((long) VibrationEffect.EFFECT_CLICK), eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), anyLong()); - verify(mNativeWrapperMock).vibratorPerformEffect( + verify(mNativeWrapperMock).perform( eq((long) VibrationEffect.EFFECT_TICK), eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), anyLong()); - verify(mNativeWrapperMock).vibratorPerformEffect( + verify(mNativeWrapperMock).perform( eq((long) VibrationEffect.EFFECT_DOUBLE_CLICK), eq((long) VibrationEffect.EFFECT_STRENGTH_LIGHT), anyLong()); - verify(mNativeWrapperMock, never()).vibratorPerformEffect( + verify(mNativeWrapperMock, never()).perform( eq((long) VibrationEffect.EFFECT_HEAVY_CLICK), anyLong(), anyLong()); } @@ -696,14 +787,14 @@ public class VibratorServiceTest { Thread.sleep(15); // Alarm vibration is never scaled. - verify(mNativeWrapperMock).vibratorSetAmplitude(eq(100)); + verify(mNativeWrapperMock).setAmplitude(eq(100)); // Notification vibrations will be scaled with SCALE_VERY_HIGH. - verify(mNativeWrapperMock).vibratorSetAmplitude(intThat(amplitude -> amplitude > 150)); + verify(mNativeWrapperMock).setAmplitude(intThat(amplitude -> amplitude > 150)); // Haptic feedback vibrations will be scaled with SCALE_LOW. - verify(mNativeWrapperMock).vibratorSetAmplitude( + verify(mNativeWrapperMock).setAmplitude( intThat(amplitude -> amplitude < 100 && amplitude > 50)); // Ringtone vibration is off. - verify(mNativeWrapperMock, never()).vibratorSetAmplitude(eq(255)); + verify(mNativeWrapperMock, never()).setAmplitude(eq(255)); } @Test @@ -733,7 +824,7 @@ public class VibratorServiceTest { vibrate(service, effect, RINGTONE_ATTRS); // Ringtone vibration is off, so only the other 3 are propagated to native. - verify(mNativeWrapperMock, times(3)).vibratorPerformComposedEffect( + verify(mNativeWrapperMock, times(3)).compose( primitivesCaptor.capture(), anyLong()); List<VibrationEffect.Composition.PrimitiveEffect[]> values = @@ -792,7 +883,12 @@ public class VibratorServiceTest { } private void mockVibratorCapabilities(int capabilities) { - when(mNativeWrapperMock.vibratorGetCapabilities()).thenReturn((long) capabilities); + when(mNativeWrapperMock.getCapabilities()).thenReturn((long) capabilities); + } + + private InputDevice createInputDeviceWithVibrator(int id) { + return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0, + null, /* hasVibrator= */ true, false, false); } private static <T> void addLocalServiceMock(Class<T> clazz, T mock) { diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java index d10e075c5136..de9a5e4f0fe7 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java @@ -18,13 +18,17 @@ package com.android.server.hdmi; import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; +import android.annotation.NonNull; import android.content.Context; import android.hardware.hdmi.HdmiControlManager; +import android.os.Looper; import android.platform.test.annotations.Presubmit; import android.provider.Settings.Global; @@ -38,15 +42,21 @@ import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + @SmallTest @Presubmit @RunWith(JUnit4.class) public final class HdmiCecConfigTest { private static final String TAG = "HdmiCecConfigTest"; + private static final int TIMEOUT_CONTENT_CHANGE_SEC = 4; + private Context mContext; @Mock private HdmiCecConfig.StorageAdapter mStorageAdapter; + @Mock private HdmiCecConfig.SettingChangeListener mSettingChangeListener; @Before public void setUp() throws Exception { @@ -1019,4 +1029,105 @@ public final class HdmiCecConfigTest { HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, Integer.toString(HdmiControlManager.SYSTEM_AUDIO_MODE_MUTING_DISABLED)); } + + @Test + public void registerChangeListener_SharedPref_BasicSanity() { + HdmiCecConfig hdmiCecConfig = HdmiCecConfig.createFromStrings( + mContext, mStorageAdapter, + "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>" + + "<cec-settings>" + + " <setting name=\"system_audio_mode_muting\"" + + " value-type=\"int\"" + + " user-configurable=\"true\">" + + " <allowed-values>" + + " <value int-value=\"0\" />" + + " <value int-value=\"1\" />" + + " </allowed-values>" + + " <default-value int-value=\"1\" />" + + " </setting>" + + "</cec-settings>", null); + hdmiCecConfig.registerChangeListener( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, + mSettingChangeListener); + hdmiCecConfig.setIntValue( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, + HdmiControlManager.SYSTEM_AUDIO_MODE_MUTING_DISABLED); + verify(mSettingChangeListener).onChange( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING); + } + + @Test + public void removeChangeListener_SharedPref_BasicSanity() { + HdmiCecConfig hdmiCecConfig = HdmiCecConfig.createFromStrings( + mContext, mStorageAdapter, + "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>" + + "<cec-settings>" + + " <setting name=\"system_audio_mode_muting\"" + + " value-type=\"int\"" + + " user-configurable=\"true\">" + + " <allowed-values>" + + " <value int-value=\"0\" />" + + " <value int-value=\"1\" />" + + " </allowed-values>" + + " <default-value int-value=\"1\" />" + + " </setting>" + + "</cec-settings>", null); + hdmiCecConfig.registerChangeListener( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, + mSettingChangeListener); + hdmiCecConfig.removeChangeListener( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, + mSettingChangeListener); + hdmiCecConfig.setIntValue( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, + HdmiControlManager.SYSTEM_AUDIO_MODE_MUTING_DISABLED); + verify(mSettingChangeListener, never()).onChange( + HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING); + } + + /** + * Externally modified Global Settings still need to be supported. This test verifies that + * setting change notification is being forwarded to listeners registered via HdmiCecConfig. + */ + @Test + public void globalSettingObserver_BasicSanity() throws Exception { + CountDownLatch notifyLatch = new CountDownLatch(1); + // Get current value of the setting in the system. + String val = Global.getString(mContext.getContentResolver(), Global.HDMI_CONTROL_ENABLED); + HdmiCecConfig hdmiCecConfig = HdmiCecConfig.createFromStrings( + mContext, mStorageAdapter, + "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>" + + "<cec-settings>" + + " <setting name=\"hdmi_cec_enabled\"" + + " value-type=\"int\"" + + " user-configurable=\"true\">" + + " <allowed-values>" + + " <value int-value=\"0\" />" + + " <value int-value=\"1\" />" + + " </allowed-values>" + + " <default-value int-value=\"1\" />" + + " </setting>" + + "</cec-settings>", null); + hdmiCecConfig.registerGlobalSettingsObserver(Looper.getMainLooper()); + HdmiCecConfig.SettingChangeListener latchUpdateListener = + new HdmiCecConfig.SettingChangeListener() { + @Override + public void onChange(@NonNull @HdmiControlManager.CecSettingName String setting) { + notifyLatch.countDown(); + assertThat(setting).isEqualTo(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED); + } + }; + hdmiCecConfig.registerChangeListener( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, + latchUpdateListener); + // Flip the value of the setting. + Global.putString(mContext.getContentResolver(), Global.HDMI_CONTROL_ENABLED, + ((val == null || val.equals("1")) ? "0" : "1")); + if (!notifyLatch.await(TIMEOUT_CONTENT_CHANGE_SEC, TimeUnit.SECONDS)) { + fail("Timed out waiting for the notify callback"); + } + hdmiCecConfig.unregisterGlobalSettingsObserver(); + // Restore the previous value of the setting in the system. + Global.putString(mContext.getContentResolver(), Global.HDMI_CONTROL_ENABLED, val); + } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java index 9d767cd94853..819bd01992cb 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java @@ -521,6 +521,41 @@ public class HdmiControlServiceTest { assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures); } + @Test + public void initializeCec_14_doesNotBroadcastReportFeatures() { + mNativeWrapper.clearResultMessages(); + mHdmiControlService.getHdmiCecConfig().setIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, + HdmiControlManager.HDMI_CEC_VERSION_1_4_b); + mHdmiControlService.setControlEnabled(true); + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + mTestLooper.dispatchAll(); + + HdmiCecMessage reportFeatures = HdmiCecMessageBuilder.buildReportFeatures( + Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0, + Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM), + mMyPlaybackDevice.getRcProfile(), mMyPlaybackDevice.getRcFeatures(), + mMyPlaybackDevice.getDeviceFeatures()); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportFeatures); + } + + @Test + public void initializeCec_20_reportsFeaturesBroadcast() { + mHdmiControlService.getHdmiCecConfig().setIntValue( + HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION, + HdmiControlManager.HDMI_CEC_VERSION_2_0); + mHdmiControlService.setControlEnabled(true); + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + mTestLooper.dispatchAll(); + + HdmiCecMessage reportFeatures = HdmiCecMessageBuilder.buildReportFeatures( + Constants.ADDR_PLAYBACK_1, HdmiControlManager.HDMI_CEC_VERSION_2_0, + Arrays.asList(DEVICE_PLAYBACK, DEVICE_AUDIO_SYSTEM), + mMyPlaybackDevice.getRcProfile(), mMyPlaybackDevice.getRcFeatures(), + mMyPlaybackDevice.getDeviceFeatures()); + assertThat(mNativeWrapper.getResultMessages()).contains(reportFeatures); + } + private static class VolumeControlFeatureCallback extends IHdmiCecVolumeControlFeatureListener.Stub { boolean mCallbackReceived = false; diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodManagerServiceTests.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodManagerServiceTests.java index 8afc3d30efa3..1db5544871bf 100644 --- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodManagerServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodManagerServiceTests.java @@ -18,6 +18,8 @@ package com.android.server.inputmethod; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -38,9 +40,9 @@ public class InputMethodManagerServiceTests { (displayId) -> { switch (displayId) { case SYSTEM_DECORATION_SUPPORT_DISPLAY_ID: - return true; + return DISPLAY_IME_POLICY_LOCAL; case NO_SYSTEM_DECORATION_SUPPORT_DISPLAY_ID: - return false; + return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; default: throw new IllegalArgumentException("Unknown displayId=" + displayId); } @@ -49,7 +51,7 @@ public class InputMethodManagerServiceTests { static InputMethodManagerService.ImeDisplayValidator sMustNotBeCalledChecker = (displayId) -> { fail("Should not pass to display config check for this test case."); - return false; + return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; }; @Test diff --git a/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java b/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java index 3f1653718fe7..00cef8fb8481 100644 --- a/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java +++ b/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java @@ -59,7 +59,7 @@ import java.util.Objects; @Presubmit public class ControllerImplTest { - private static final long ARBITRARY_TIME = 12345L; + private static final long ARBITRARY_TIME_MILLIS = 12345L; private static final LocationTimeZoneEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 = createLocationTimeZoneEvent(EVENT_TYPE_SUCCESS, asList("Europe/London")); @@ -935,7 +935,7 @@ public class ControllerImplTest { private static LocationTimeZoneEvent createLocationTimeZoneEvent( int eventType, @Nullable List<String> timeZoneIds) { LocationTimeZoneEvent.Builder builder = new LocationTimeZoneEvent.Builder() - .setElapsedRealtimeNanos(ARBITRARY_TIME) + .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS) .setEventType(eventType); if (timeZoneIds != null) { builder.setTimeZoneIds(timeZoneIds); diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java index 3846be09a6c1..34cefec4655b 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java @@ -134,7 +134,7 @@ public class DexoptUtilsTest { private List<SharedLibraryInfo> createMockSharedLibrary(String [] sharedLibrary) { SharedLibraryInfo info = new SharedLibraryInfo(null, null, Arrays.asList(sharedLibrary), - null, 0L, SharedLibraryInfo.TYPE_STATIC, null, null, null); + null, 0L, SharedLibraryInfo.TYPE_STATIC, null, null, null, false /* isNative */); ArrayList<SharedLibraryInfo> libraries = new ArrayList<>(); libraries.add(info); return libraries; diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java index eedc9781aa40..c42f936d3ab4 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackStoreTest.java @@ -110,6 +110,8 @@ public class RollbackStoreTest { @Rule public TemporaryFolder mFolder = new TemporaryFolder(); + @Rule + public TemporaryFolder mHistoryDir = new TemporaryFolder(); private File mRollbackDir; @@ -117,7 +119,7 @@ public class RollbackStoreTest { @Before public void setUp() throws Exception { - mRollbackStore = new RollbackStore(mFolder.getRoot()); + mRollbackStore = new RollbackStore(mFolder.getRoot(), mHistoryDir.getRoot()); mRollbackDir = mFolder.newFolder(ID + ""); mFolder.newFile("rollback.json"); } @@ -202,6 +204,8 @@ public class RollbackStoreTest { origRb.info.getPackages().add(pkgInfo1); origRb.info.getPackages().add(pkgInfo2); + origRb.setState(Rollback.ROLLBACK_STATE_AVAILABLE, "hello world"); + RollbackStore.saveRollback(origRb); List<Rollback> loadedRollbacks = mRollbackStore.loadRollbacks(); @@ -324,10 +328,26 @@ public class RollbackStoreTest { assertThat(expectedFile.exists()).isFalse(); } - private void assertRollbacksAreEquivalent(Rollback b, Rollback a) { - assertThat(b.info.getRollbackId()).isEqualTo(ID); + @Test + public void saveToHistoryAndLoad() { + Rollback origRb = mRollbackStore.createNonStagedRollback( + ID, USER, INSTALLER, null, new SparseIntArray(0)); + mRollbackStore.saveRollbackToHistory(origRb); + + List<Rollback> loadedRollbacks = mRollbackStore.loadHistorialRollbacks(); + assertThat(loadedRollbacks).hasSize(1); + Rollback loadedRb = loadedRollbacks.get(0); + + assertRollbacksAreEquivalentExcludingBackupDir(loadedRb, origRb); + } + private void assertRollbacksAreEquivalent(Rollback b, Rollback a) { assertThat(b.getBackupDir()).isEqualTo(a.getBackupDir()); + assertRollbacksAreEquivalentExcludingBackupDir(b, a); + } + + private void assertRollbacksAreEquivalentExcludingBackupDir(Rollback b, Rollback a) { + assertThat(b.info.getRollbackId()).isEqualTo(ID); assertThat(b.isRestoreUserDataInProgress()) .isEqualTo(a.isRestoreUserDataInProgress()); @@ -337,6 +357,7 @@ public class RollbackStoreTest { assertThat(b.isEnabling()).isEqualTo(a.isEnabling()); assertThat(b.isAvailable()).isEqualTo(a.isAvailable()); assertThat(b.isCommitted()).isEqualTo(a.isCommitted()); + assertThat(b.getStateDescription()).isEqualTo(a.getStateDescription()); assertThat(b.isStaged()).isEqualTo(a.isStaged()); diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java index cd2c9230221c..cf1ed4815a74 100644 --- a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java +++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java @@ -123,7 +123,7 @@ public class RollbackUnitTest { public void deletedRollbackCannotBeMadeAvailable() { Rollback rollback = new Rollback(123, new File("/test/testing"), -1, USER, INSTALLER); - rollback.delete(mMockDataHelper); + rollback.delete(mMockDataHelper, "test"); assertThat(rollback.isDeleted()).isTrue(); @@ -221,7 +221,7 @@ public class RollbackUnitTest { PackageRollbackInfo pkgInfo2 = newPkgInfoFor(PKG_2, 18, 12, true); rollback.info.getPackages().addAll(Arrays.asList(pkgInfo1, pkgInfo2)); - rollback.delete(mMockDataHelper); + rollback.delete(mMockDataHelper, "test"); assertThat(rollback.isDeleted()).isTrue(); @@ -247,7 +247,7 @@ public class RollbackUnitTest { verify(mMockDataHelper).snapshotAppData(eq(123), pkgRollbackInfoFor(PKG_2), eq(userIds)); - rollback.delete(mMockDataHelper); + rollback.delete(mMockDataHelper, "test"); verify(mMockDataHelper).destroyAppDataSnapshot(eq(123), pkgRollbackInfoFor(PKG_2), eq(111)); verify(mMockDataHelper).destroyAppDataSnapshot(eq(123), pkgRollbackInfoFor(PKG_2), eq(222)); @@ -269,7 +269,7 @@ public class RollbackUnitTest { verify(mMockDataHelper).snapshotAppData(eq(123), pkgRollbackInfoFor(PKG_2), eq(userIds)); - rollback.delete(mMockDataHelper); + rollback.delete(mMockDataHelper, "test"); verify(mMockDataHelper, never()) .destroyAppDataSnapshot(anyInt(), pkgRollbackInfoFor(PKG_2), anyInt()); diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java index e101a06feb4e..4a44005e9602 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java @@ -245,7 +245,7 @@ public class TimeDetectorServiceTest { } @Override - public void handleAutoTimeDetectionChanged() { + public void handleAutoTimeConfigChanged() { mHandleAutoTimeDetectionChangedCalled = true; } diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java index 1be074dfa5a3..c23fb8028224 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java @@ -16,6 +16,9 @@ package com.android.server.timedetector; +import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK; +import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -25,32 +28,39 @@ import static org.junit.Assert.fail; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; import android.app.timedetector.TelephonyTimeSuggestion; -import android.icu.util.Calendar; -import android.icu.util.GregorianCalendar; -import android.icu.util.TimeZone; import android.os.TimestampedValue; import androidx.test.runner.AndroidJUnit4; +import com.android.server.timedetector.TimeDetectorStrategy.Origin; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; @RunWith(AndroidJUnit4.class) public class TimeDetectorStrategyImplTest { - private static final TimestampedValue<Long> ARBITRARY_CLOCK_INITIALIZATION_INFO = + private static final Instant TIME_LOWER_BOUND = createUtcTime(2009, 1, 1, 12, 0, 0); + + private static final TimestampedValue<Instant> ARBITRARY_CLOCK_INITIALIZATION_INFO = new TimestampedValue<>( 123456789L /* realtimeClockMillis */, - createUtcTime(2008, 5, 23, 12, 0, 0)); + createUtcTime(2010, 5, 23, 12, 0, 0)); + + // This is the traditional ordering for time detection on Android. + private static final @Origin int [] PROVIDERS_PRIORITY = { ORIGIN_TELEPHONY, ORIGIN_NETWORK }; /** * An arbitrary time, very different from the {@link #ARBITRARY_CLOCK_INITIALIZATION_INFO} * time. Can be used as the basis for time suggestions. */ - private static final long ARBITRARY_TEST_TIME_MILLIS = createUtcTime(2018, 1, 1, 12, 0, 0); + private static final Instant ARBITRARY_TEST_TIME = createUtcTime(2018, 1, 1, 12, 0, 0); private static final int ARBITRARY_SLOT_INDEX = 123456; @@ -67,10 +77,10 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(true); int slotIndex = ARBITRARY_SLOT_INDEX; - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; TelephonyTimeSuggestion timeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); mScript.simulateTimePassing() .simulateTelephonyTimeSuggestion(timeSuggestion); @@ -106,9 +116,9 @@ public class TimeDetectorStrategyImplTest { // Send the first time signal. It should be used. { TelephonyTimeSuggestion timeSuggestion1 = - mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME_MILLIS); + mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME); - // Increment the the device clocks to simulate the passage of time. + // Increment the device clocks to simulate the passage of time. mScript.simulateTimePassing(clockIncrementMillis); long expectedSystemClockMillis1 = @@ -157,13 +167,13 @@ public class TimeDetectorStrategyImplTest { // uses the lowest slotIndex when multiple telephony suggestions are available. int slotIndex1 = ARBITRARY_SLOT_INDEX; int slotIndex2 = ARBITRARY_SLOT_INDEX + 1; - long slotIndex1TimeMillis = ARBITRARY_TEST_TIME_MILLIS; - long slotIndex2TimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(1).toMillis(); + Instant slotIndex1Time = ARBITRARY_TEST_TIME; + Instant slotIndex2Time = ARBITRARY_TEST_TIME.plus(Duration.ofDays(1)); // Make a suggestion with slotIndex2. { TelephonyTimeSuggestion slotIndex2TimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time); mScript.simulateTimePassing(); long expectedSystemClockMillis = @@ -180,7 +190,7 @@ public class TimeDetectorStrategyImplTest { // Now make a different suggestion with slotIndex1. { TelephonyTimeSuggestion slotIndex1TimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1TimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1Time); mScript.simulateTimePassing(); long expectedSystemClockMillis = @@ -198,7 +208,7 @@ public class TimeDetectorStrategyImplTest { // slotIndex1 suggestion will still "win". { TelephonyTimeSuggestion slotIndex2TimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time); mScript.simulateTimePassing(); mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion) @@ -213,7 +223,7 @@ public class TimeDetectorStrategyImplTest { // is in an older "bucket". { TelephonyTimeSuggestion slotIndex2TimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2TimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time); mScript.simulateTimePassing(); long expectedSystemClockMillis = @@ -232,7 +242,7 @@ public class TimeDetectorStrategyImplTest { int slotIndex = ARBITRARY_SLOT_INDEX; TelephonyTimeSuggestion timeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME_MILLIS); + mScript.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME); mScript.simulateTimePassing() .simulateTelephonyTimeSuggestion(timeSuggestion) .verifySystemClockWasNotSetAndResetCallTracking() @@ -246,11 +256,11 @@ public class TimeDetectorStrategyImplTest { .pokeThresholds(systemClockUpdateThreshold) .pokeAutoTimeDetectionEnabled(true); - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; int slotIndex = ARBITRARY_SLOT_INDEX; TelephonyTimeSuggestion timeSuggestion1 = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime(); // Initialize the strategy / device with a time set from a telephony suggestion. @@ -300,6 +310,23 @@ public class TimeDetectorStrategyImplTest { } @Test + public void telephonyTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + int slotIndex = ARBITRARY_SLOT_INDEX; + Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); + + TelephonyTimeSuggestion timeSuggestion = + mScript.generateTelephonyTimeSuggestion( + slotIndex, suggestedTime); + + mScript.simulateTelephonyTimeSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking() + .assertLatestTelephonySuggestion(slotIndex, null); + } + + @Test public void testSuggestTelephonyTime_timeDetectionToggled() { final int clockIncrementMillis = 100; final int systemClockUpdateThreshold = 2000; @@ -308,9 +335,9 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(false); int slotIndex = ARBITRARY_SLOT_INDEX; - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; TelephonyTimeSuggestion timeSuggestion1 = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime(); // Simulate time passing. @@ -366,9 +393,9 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(true); int slotIndex = ARBITRARY_SLOT_INDEX; - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; TelephonyTimeSuggestion telephonySuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); mScript.simulateTimePassing(); @@ -397,7 +424,7 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(false); ManualTimeSuggestion timeSuggestion = - mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS); + mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME); mScript.simulateTimePassing(); @@ -416,9 +443,9 @@ public class TimeDetectorStrategyImplTest { int slotIndex = ARBITRARY_SLOT_INDEX; // Simulate a telephony suggestion. - long testTimeMillis = ARBITRARY_TEST_TIME_MILLIS; + Instant testTime = ARBITRARY_TEST_TIME; TelephonyTimeSuggestion telephonyTimeSuggestion = - mScript.generateTelephonyTimeSuggestion(slotIndex, testTimeMillis); + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); // Simulate the passage of time. mScript.simulateTimePassing(); @@ -441,9 +468,9 @@ public class TimeDetectorStrategyImplTest { mScript.simulateTimePassing(); // Simulate a manual suggestion 1 day different from the auto suggestion. - long manualTimeMillis = testTimeMillis + Duration.ofDays(1).toMillis(); + Instant manualTime = testTime.plus(Duration.ofDays(1)); ManualTimeSuggestion manualTimeSuggestion = - mScript.generateManualTimeSuggestion(manualTimeMillis); + mScript.generateManualTimeSuggestion(manualTime); mScript.simulateTimePassing(); long expectedManualClockMillis = @@ -469,16 +496,13 @@ public class TimeDetectorStrategyImplTest { .assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion); } - /** - * Manual suggestions should be ignored if auto time is enabled. - */ @Test - public void testSuggestManualTime_autoTimeEnabled() { + public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(true); ManualTimeSuggestion timeSuggestion = - mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS); + mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME); mScript.simulateTimePassing() .simulateManualTimeSuggestion(timeSuggestion, false /* expectedResult */) @@ -486,12 +510,25 @@ public class TimeDetectorStrategyImplTest { } @Test + public void manualTimeSuggestion_ignoresTimeLowerBound() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(false); + Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); + + ManualTimeSuggestion timeSuggestion = + mScript.generateManualTimeSuggestion(suggestedTime); + + mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */) + .verifySystemClockWasSetAndResetCallTracking(suggestedTime.toEpochMilli()); + } + + @Test public void testSuggestNetworkTime_autoTimeEnabled() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(true); NetworkTimeSuggestion timeSuggestion = - mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS); + mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME); mScript.simulateTimePassing(); @@ -507,7 +544,7 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(false); NetworkTimeSuggestion timeSuggestion = - mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME_MILLIS); + mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME); mScript.simulateTimePassing() .simulateNetworkTimeSuggestion(timeSuggestion) @@ -520,16 +557,16 @@ public class TimeDetectorStrategyImplTest { .pokeAutoTimeDetectionEnabled(true); // Three obviously different times that could not be mistaken for each other. - long networkTimeMillis1 = ARBITRARY_TEST_TIME_MILLIS; - long networkTimeMillis2 = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(30).toMillis(); - long telephonyTimeMillis = ARBITRARY_TEST_TIME_MILLIS + Duration.ofDays(60).toMillis(); + Instant networkTime1 = ARBITRARY_TEST_TIME; + Instant networkTime2 = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60)); // A small increment used to simulate the passage of time, but not enough to interfere with // macro-level time changes associated with suggestion age. final long smallTimeIncrementMillis = 101; // A network suggestion is made. It should be used because there is no telephony suggestion. NetworkTimeSuggestion networkTimeSuggestion1 = - mScript.generateNetworkTimeSuggestion(networkTimeMillis1); + mScript.generateNetworkTimeSuggestion(networkTime1); mScript.simulateTimePassing(smallTimeIncrementMillis) .simulateNetworkTimeSuggestion(networkTimeSuggestion1) .verifySystemClockWasSetAndResetCallTracking( @@ -548,7 +585,7 @@ public class TimeDetectorStrategyImplTest { // Now a telephony suggestion is made. Telephony suggestions are prioritized over network // suggestions so it should "win". TelephonyTimeSuggestion telephonyTimeSuggestion = - mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeMillis); + mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); mScript.simulateTimePassing(smallTimeIncrementMillis) .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) .verifySystemClockWasSetAndResetCallTracking( @@ -568,7 +605,7 @@ public class TimeDetectorStrategyImplTest { // Now another network suggestion is made. Telephony suggestions are prioritized over // network suggestions so the latest telephony suggestion should still "win". NetworkTimeSuggestion networkTimeSuggestion2 = - mScript.generateNetworkTimeSuggestion(networkTimeMillis2); + mScript.generateNetworkTimeSuggestion(networkTime2); mScript.simulateTimePassing(smallTimeIncrementMillis) .simulateNetworkTimeSuggestion(networkTimeSuggestion2) .verifySystemClockWasNotSetAndResetCallTracking(); @@ -612,6 +649,87 @@ public class TimeDetectorStrategyImplTest { assertNull(mScript.peekBestTelephonySuggestion()); } + @Test + public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); + NetworkTimeSuggestion timeSuggestion = mScript + .generateNetworkTimeSuggestion(suggestedTime); + + mScript.simulateNetworkTimeSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking() + .assertLatestNetworkSuggestion(null); + } + + @Test + public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + Instant networkTime = ARBITRARY_TEST_TIME; + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + + NetworkTimeSuggestion networkTimeSuggestion = + mScript.generateNetworkTimeSuggestion(networkTime); + TelephonyTimeSuggestion telephonyTimeSuggestion = + mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); + + mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion) + .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) + .assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli()); + } + + @Test + public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + Instant networkTime = ARBITRARY_TEST_TIME; + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + + NetworkTimeSuggestion networkTimeSuggestion = + mScript.generateNetworkTimeSuggestion(networkTime); + TelephonyTimeSuggestion telephonyTimeSuggestion = + mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); + + mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) + .simulateNetworkTimeSuggestion(networkTimeSuggestion) + .assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli()); + } + + @Test + public void whenHighestPrioritySuggestionIsNotAvailable_fallbacksToNext() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true); + + NetworkTimeSuggestion timeSuggestion = + mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateNetworkTimeSuggestion(timeSuggestion) + .assertLatestNetworkSuggestion(timeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli()); + } + + @Test + public void suggestionsFromSourceNotListedInPrioritiesList_areIgnored() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(new int[]{ORIGIN_TELEPHONY}); + + NetworkTimeSuggestion timeSuggestion = mScript.generateNetworkTimeSuggestion( + ARBITRARY_TEST_TIME); + + mScript.simulateNetworkTimeSuggestion(timeSuggestion) + .assertLatestNetworkSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + /** * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving * like the real thing should, it also asserts preconditions. @@ -622,6 +740,7 @@ public class TimeDetectorStrategyImplTest { private long mElapsedRealtimeMillis; private long mSystemClockMillis; private int mSystemClockUpdateThresholdMillis = 2000; + private int[] mAutoOriginPriorities = PROVIDERS_PRIORITY; // Tracking operations. private boolean mSystemClockWasSet; @@ -637,6 +756,16 @@ public class TimeDetectorStrategyImplTest { } @Override + public Instant autoTimeLowerBound() { + return TIME_LOWER_BOUND; + } + + @Override + public int[] getAutoOriginPriorities() { + return mAutoOriginPriorities; + } + + @Override public void acquireWakeLock() { if (mWakeLockAcquired) { fail("Wake lock already acquired"); @@ -685,6 +814,10 @@ public class TimeDetectorStrategyImplTest { mAutoTimeDetectionEnabled = enabled; } + void pokeAutoOriginPriorities(@Origin int[] autoOriginPriorities) { + mAutoOriginPriorities = autoOriginPriorities; + } + long peekElapsedRealtimeMillis() { return mElapsedRealtimeMillis; } @@ -703,7 +836,10 @@ public class TimeDetectorStrategyImplTest { } void verifySystemClockNotSet() { - assertFalse(mSystemClockWasSet); + assertFalse( + String.format("System clock was manipulated and set to %s(=%s)", + Instant.ofEpochMilli(mSystemClockMillis), mSystemClockMillis), + mSystemClockWasSet); } void verifySystemClockWasSet(long expectedSystemClockMillis) { @@ -739,9 +875,9 @@ public class TimeDetectorStrategyImplTest { return this; } - Script pokeFakeClocks(TimestampedValue<Long> timeInfo) { + Script pokeFakeClocks(TimestampedValue<Instant> timeInfo) { mFakeCallback.pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis()); - mFakeCallback.pokeSystemClockMillis(timeInfo.getValue()); + mFakeCallback.pokeSystemClockMillis(timeInfo.getValue().toEpochMilli()); return this; } @@ -750,6 +886,11 @@ public class TimeDetectorStrategyImplTest { return this; } + Script pokeAutoOriginPriorities(@Origin int[] autoOriginPriorites) { + mFakeCallback.pokeAutoOriginPriorities(autoOriginPriorites); + return this; + } + long peekElapsedRealtimeMillis() { return mFakeCallback.peekElapsedRealtimeMillis(); } @@ -765,7 +906,13 @@ public class TimeDetectorStrategyImplTest { Script simulateManualTimeSuggestion( ManualTimeSuggestion timeSuggestion, boolean expectedResult) { - assertEquals(expectedResult, mTimeDetectorStrategy.suggestManualTime(timeSuggestion)); + String errorMessage = expectedResult + ? "Manual time suggestion was ignored, but expected to be accepted." + : "Manual time suggestion was accepted, but expected to be ignored."; + assertEquals( + errorMessage, + expectedResult, + mTimeDetectorStrategy.suggestManualTime(timeSuggestion)); return this; } @@ -776,7 +923,7 @@ public class TimeDetectorStrategyImplTest { Script simulateAutoTimeDetectionToggle() { mFakeCallback.simulateAutoTimeZoneDetectionToggle(); - mTimeDetectorStrategy.handleAutoTimeDetectionChanged(); + mTimeDetectorStrategy.handleAutoTimeConfigChanged(); return this; } @@ -808,7 +955,10 @@ public class TimeDetectorStrategyImplTest { * White box test info: Asserts the latest suggestion for the slotIndex is as expected. */ Script assertLatestTelephonySuggestion(int slotIndex, TelephonyTimeSuggestion expected) { - assertEquals(expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex)); + assertEquals( + "Expected to see " + expected + " at slotIndex=" + slotIndex + ", but got " + + mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex), + expected, mTimeDetectorStrategy.getLatestTelephonySuggestion(slotIndex)); return this; } @@ -840,9 +990,11 @@ public class TimeDetectorStrategyImplTest { * Generates a ManualTimeSuggestion using the current elapsed realtime clock for the * reference time. */ - ManualTimeSuggestion generateManualTimeSuggestion(long timeMillis) { + ManualTimeSuggestion generateManualTimeSuggestion(Instant suggestedTime) { TimestampedValue<Long> utcTime = - new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis); + new TimestampedValue<>( + mFakeCallback.peekElapsedRealtimeMillis(), + suggestedTime.toEpochMilli()); return new ManualTimeSuggestion(utcTime); } @@ -850,21 +1002,33 @@ public class TimeDetectorStrategyImplTest { * Generates a {@link TelephonyTimeSuggestion} using the current elapsed realtime clock for * the reference time. */ - TelephonyTimeSuggestion generateTelephonyTimeSuggestion(int slotIndex, Long timeMillis) { - TimestampedValue<Long> time = null; - if (timeMillis != null) { - time = new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis); - } + TelephonyTimeSuggestion generateTelephonyTimeSuggestion(int slotIndex, long timeMillis) { + TimestampedValue<Long> time = + new TimestampedValue<>(peekElapsedRealtimeMillis(), timeMillis); return createTelephonyTimeSuggestion(slotIndex, time); } /** + * Generates a {@link TelephonyTimeSuggestion} using the current elapsed realtime clock for + * the reference time. + */ + TelephonyTimeSuggestion generateTelephonyTimeSuggestion( + int slotIndex, Instant suggestedTime) { + if (suggestedTime == null) { + return createTelephonyTimeSuggestion(slotIndex, null); + } + return generateTelephonyTimeSuggestion(slotIndex, suggestedTime.toEpochMilli()); + } + + /** * Generates a NetworkTimeSuggestion using the current elapsed realtime clock for the * reference time. */ - NetworkTimeSuggestion generateNetworkTimeSuggestion(long timeMillis) { + NetworkTimeSuggestion generateNetworkTimeSuggestion(Instant suggestedTime) { TimestampedValue<Long> utcTime = - new TimestampedValue<>(mFakeCallback.peekElapsedRealtimeMillis(), timeMillis); + new TimestampedValue<>( + mFakeCallback.peekElapsedRealtimeMillis(), + suggestedTime.toEpochMilli()); return new NetworkTimeSuggestion(utcTime); } @@ -884,11 +1048,9 @@ public class TimeDetectorStrategyImplTest { .build(); } - private static long createUtcTime(int year, int monthInYear, int day, int hourOfDay, int minute, - int second) { - Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("Etc/UTC")); - cal.clear(); - cal.set(year, monthInYear - 1, day, hourOfDay, minute, second); - return cal.getTimeInMillis(); + private static Instant createUtcTime(int year, int monthInYear, int day, int hourOfDay, + int minute, int second) { + return LocalDateTime.of(year, monthInYear, day, hourOfDay, minute, second) + .toInstant(ZoneOffset.UTC); } } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java new file mode 100644 index 000000000000..fa8e36741bcc --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vibrator; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.ContextWrapper; +import android.hardware.input.IInputDevicesChangedListener; +import android.hardware.input.IInputManager; +import android.hardware.input.InputManager; +import android.os.Handler; +import android.os.Process; +import android.os.VibrationAttributes; +import android.os.VibrationEffect; +import android.os.test.TestLooper; +import android.platform.test.annotations.Presubmit; +import android.view.InputDevice; + +import androidx.test.InstrumentationRegistry; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** + * Tests for {@link InputDeviceDelegate}. + * + * Build/Install/Run: + * atest FrameworksServicesTests:InputDeviceDelegateTest + */ +@Presubmit +public class InputDeviceDelegateTest { + + private static final int UID = Process.ROOT_UID; + private static final String PACKAGE_NAME = "package"; + private static final String REASON = "some reason"; + private static final VibrationAttributes VIBRATION_ATTRIBUTES = + new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build(); + + @Rule public MockitoRule rule = MockitoJUnit.rule(); + + @Mock private IInputManager mIInputManagerMock; + + private TestLooper mTestLooper; + private ContextWrapper mContextSpy; + private InputDeviceDelegate mInputDeviceDelegate; + private IInputDevicesChangedListener mIInputDevicesChangedListener; + + @Before + public void setUp() throws Exception { + mTestLooper = new TestLooper(); + mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); + InputManager inputManager = InputManager.resetInstance(mIInputManagerMock); + + when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager); + doAnswer(invocation -> mIInputDevicesChangedListener = invocation.getArgument(0)) + .when(mIInputManagerMock).registerInputDevicesChangedListener(any()); + + mInputDeviceDelegate = new InputDeviceDelegate( + mContextSpy, new Handler(mTestLooper.getLooper())); + } + + @Test + public void onInputDeviceAdded_withSettingsDisabled_ignoresNewDevice() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]); + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ false); + assertFalse(mInputDeviceDelegate.isAvailable()); + + when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn(createInputDeviceWithVibrator(1)); + mInputDeviceDelegate.onInputDeviceAdded(1); + + assertFalse(mInputDeviceDelegate.isAvailable()); + verify(mIInputManagerMock, never()).getInputDevice(anyInt()); + } + + @Test + public void onInputDeviceAdded_withDeviceWithoutVibrator_ignoresNewDevice() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]); + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + assertFalse(mInputDeviceDelegate.isAvailable()); + + when(mIInputManagerMock.getInputDevice(eq(1))) + .thenReturn(createInputDeviceWithoutVibrator(1)); + updateInputDevices(new int[]{1}); + + assertFalse(mInputDeviceDelegate.isAvailable()); + verify(mIInputManagerMock).getInputDevice(eq(1)); + } + + @Test + public void onInputDeviceAdded_withDeviceWithVibrator_addsNewDevice() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]); + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + assertFalse(mInputDeviceDelegate.isAvailable()); + + when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn(createInputDeviceWithVibrator(1)); + updateInputDevices(new int[]{1}); + + assertTrue(mInputDeviceDelegate.isAvailable()); + verify(mIInputManagerMock).getInputDevice(eq(1)); + } + + @Test + public void onInputDeviceChanged_withSettingsDisabled_ignoresDevice() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn(createInputDeviceWithVibrator(1)); + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ false); + + updateInputDevices(new int[]{1}); + assertFalse(mInputDeviceDelegate.isAvailable()); + verify(mIInputManagerMock, never()).getInputDevice(anyInt()); + } + + @Test + public void onInputDeviceChanged_deviceLosesVibrator_removesDevice() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(eq(1))) + .thenReturn(createInputDeviceWithVibrator(1), createInputDeviceWithoutVibrator(1)); + + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + assertTrue(mInputDeviceDelegate.isAvailable()); + + updateInputDevices(new int[]{1}); + assertFalse(mInputDeviceDelegate.isAvailable()); + verify(mIInputManagerMock, times(2)).getInputDevice(eq(1)); + } + + @Test + public void onInputDeviceChanged_deviceLost_removesDevice() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(eq(1))) + .thenReturn(createInputDeviceWithVibrator(1), (InputDevice) null); + + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + assertTrue(mInputDeviceDelegate.isAvailable()); + + updateInputDevices(new int[]{1}); + assertFalse(mInputDeviceDelegate.isAvailable()); + verify(mIInputManagerMock, times(2)).getInputDevice(eq(1)); + } + + @Test + public void onInputDeviceChanged_deviceAddsVibrator_addsDevice() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(eq(1))) + .thenReturn(createInputDeviceWithoutVibrator(1), createInputDeviceWithVibrator(1)); + + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + assertFalse(mInputDeviceDelegate.isAvailable()); + + updateInputDevices(new int[]{1}); + assertTrue(mInputDeviceDelegate.isAvailable()); + verify(mIInputManagerMock, times(2)).getInputDevice(eq(1)); + } + + @Test + public void onInputDeviceRemoved_removesDevice() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1, 2}); + when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn( + createInputDeviceWithoutVibrator(1)); + when(mIInputManagerMock.getInputDevice(eq(2))).thenReturn(createInputDeviceWithVibrator(2)); + + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + assertTrue(mInputDeviceDelegate.isAvailable()); + + updateInputDevices(new int[]{1}); + assertFalse(mInputDeviceDelegate.isAvailable()); + } + + @Test + public void updateInputDeviceVibrators_usesFlagToLoadDeviceList() throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1, 2}); + when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn(createInputDeviceWithVibrator(1)); + when(mIInputManagerMock.getInputDevice(eq(2))).thenReturn(createInputDeviceWithVibrator(2)); + + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + assertTrue(mInputDeviceDelegate.isAvailable()); + + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ false); + assertFalse(mInputDeviceDelegate.isAvailable()); + } + + @Test + public void updateInputDeviceVibrators_withDeviceWithoutVibrator_deviceIsIgnored() + throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mIInputManagerMock.getInputDevice(eq(1))) + .thenReturn(createInputDeviceWithoutVibrator(1)); + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + assertFalse(mInputDeviceDelegate.isAvailable()); + } + + @Test + public void vibrateIfAvailable_withNoInputDevice_returnsFalse() { + VibrationEffect effect = VibrationEffect.createOneShot(100, 255); + assertFalse(mInputDeviceDelegate.isAvailable()); + assertFalse(mInputDeviceDelegate.vibrateIfAvailable( + UID, PACKAGE_NAME, effect, REASON, VIBRATION_ATTRIBUTES)); + } + + @Test + public void vibrateIfAvailable_withInputDevices_returnsTrueAndVibratesAllDevices() + throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1, 2}); + when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn(createInputDeviceWithVibrator(1)); + when(mIInputManagerMock.getInputDevice(eq(2))).thenReturn(createInputDeviceWithVibrator(2)); + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + + VibrationEffect effect = VibrationEffect.createOneShot(100, 255); + assertTrue(mInputDeviceDelegate.vibrateIfAvailable( + UID, PACKAGE_NAME, effect, REASON, VIBRATION_ATTRIBUTES)); + verify(mIInputManagerMock).vibrate(eq(1), same(effect), any()); + verify(mIInputManagerMock).vibrate(eq(2), same(effect), any()); + } + + @Test + public void cancelVibrateIfAvailable_withNoInputDevice_returnsFalse() throws Exception { + assertFalse(mInputDeviceDelegate.isAvailable()); + assertFalse(mInputDeviceDelegate.cancelVibrateIfAvailable()); + verify(mIInputManagerMock, never()).cancelVibrate(anyInt(), any()); + } + + @Test + public void cancelVibrateIfAvailable_withInputDevices_returnsTrueAndStopsAllDevices() + throws Exception { + when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{1, 2}); + when(mIInputManagerMock.getInputDevice(eq(1))).thenReturn(createInputDeviceWithVibrator(1)); + when(mIInputManagerMock.getInputDevice(eq(2))).thenReturn(createInputDeviceWithVibrator(2)); + mInputDeviceDelegate.updateInputDeviceVibrators(/* vibrateInputDevices= */ true); + + assertTrue(mInputDeviceDelegate.isAvailable()); + assertTrue(mInputDeviceDelegate.cancelVibrateIfAvailable()); + verify(mIInputManagerMock).cancelVibrate(eq(1), any()); + verify(mIInputManagerMock).cancelVibrate(eq(2), any()); + } + + private void updateInputDevices(int[] deviceIds) throws Exception { + int[] deviceIdsAndGenerations = new int[deviceIds.length * 2]; + for (int i = 0; i < deviceIdsAndGenerations.length; i += 2) { + deviceIdsAndGenerations[i] = deviceIds[i / 2]; + deviceIdsAndGenerations[i + 1] = 2; // update by increasing it's generation to 2. + } + // Force initialization of mIInputDevicesChangedListener, if it still haven't + InputManager.getInstance().getInputDeviceIds(); + mIInputDevicesChangedListener.onInputDevicesChanged(deviceIdsAndGenerations); + // Makes sure all callbacks from InputDeviceDelegate are executed. + mTestLooper.dispatchAll(); + } + + private InputDevice createInputDeviceWithVibrator(int id) { + return createInputDevice(id, /* hasVibrator= */ true); + } + + private InputDevice createInputDeviceWithoutVibrator(int id) { + return createInputDevice(id, /* hasVibrator= */ false); + } + + private InputDevice createInputDevice(int id, boolean hasVibrator) { + return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0, + null, hasVibrator, false, false); + } +} diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java index 2cc999283184..04c2cb3b1148 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java @@ -18,6 +18,7 @@ package com.android.server.vibrator; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.spy; @@ -33,6 +34,7 @@ import android.media.AudioManager; import android.os.Handler; import android.os.UserHandle; import android.os.VibrationAttributes; +import android.os.VibrationEffect; import android.os.Vibrator; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -271,6 +273,15 @@ public class VibrationSettingsTest { mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE)); } + @Test + public void getFallbackEffect_returnsEffectsFromSettings() { + assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_TICK)); + assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_TEXTURE_TICK)); + assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_CLICK)); + assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_HEAVY_CLICK)); + assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_DOUBLE_CLICK)); + } + private void setUserSetting(String settingName, int value) { Settings.System.putIntForUser( mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT); diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java new file mode 100644 index 000000000000..1f163bd3282b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.vibrator; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.notNull; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.content.ContentResolver; +import android.content.ContextWrapper; +import android.hardware.vibrator.IVibrator; +import android.os.IBinder; +import android.os.IVibratorStateListener; +import android.os.VibrationEffect; +import android.os.Vibrator; +import android.os.test.TestLooper; +import android.platform.test.annotations.Presubmit; + +import androidx.test.InstrumentationRegistry; + +import com.android.internal.util.test.FakeSettingsProvider; +import com.android.internal.util.test.FakeSettingsProviderRule; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** + * Tests for {@link VibratorController}. + * + * Build/Install/Run: + * atest FrameworksServicesTests:VibratorControllerTest + */ +@Presubmit +public class VibratorControllerTest { + + @Rule public MockitoRule rule = MockitoJUnit.rule(); + @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); + + @Mock private VibratorController.OnVibrationCompleteListener mOnCompleteListenerMock; + @Mock private VibratorController.NativeWrapper mNativeWrapperMock; + @Mock private IVibratorStateListener mVibratorStateListenerMock; + @Mock private IBinder mVibratorStateListenerBinderMock; + + private TestLooper mTestLooper; + private ContextWrapper mContextSpy; + + @Before + public void setUp() throws Exception { + mTestLooper = new TestLooper(); + mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext())); + + ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy); + when(mContextSpy.getContentResolver()).thenReturn(contentResolver); + when(mVibratorStateListenerMock.asBinder()).thenReturn(mVibratorStateListenerBinderMock); + } + + private VibratorController createController() { + return new VibratorController(/* vibratorId= */ 0, mOnCompleteListenerMock, + mNativeWrapperMock); + } + + private VibratorController createController(int vibratorId) { + return new VibratorController(vibratorId, mOnCompleteListenerMock, mNativeWrapperMock); + } + + @Test + public void createController_initializesNativeWrapper() { + int vibratorId = 13; + VibratorController controller = createController(vibratorId); + assertEquals(vibratorId, controller.getVibratorId()); + verify(mNativeWrapperMock).init(eq(vibratorId), notNull()); + } + + @Test + public void isAvailable_withVibratorHalPresent_returnsTrue() { + when(mNativeWrapperMock.isAvailable()).thenReturn(true); + assertTrue(createController().isAvailable()); + } + + @Test + public void isAvailable_withNoVibratorHalPresent_returnsFalse() { + when(mNativeWrapperMock.isAvailable()).thenReturn(false); + assertFalse(createController().isAvailable()); + } + + @Test + public void hasCapability_withSupport_returnsTrue() { + mockVibratorCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL); + assertTrue(createController().hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)); + } + + @Test + public void hasCapability_withNoSupport_returnsFalse() { + assertFalse(createController().hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)); + assertFalse(createController().hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)); + assertFalse(createController().hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)); + assertFalse(createController().hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)); + assertFalse(createController().hasCapability(IVibrator.CAP_ON_CALLBACK)); + } + + @Test + public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() { + when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null); + assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN}, + createController().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK})); + } + + @Test + public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() { + int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK}; + + when(mNativeWrapperMock.getSupportedEffects()) + .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); + assertArrayEquals( + new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES, + Vibrator.VIBRATION_EFFECT_SUPPORT_NO}, + createController().areEffectsSupported(effects)); + } + + @Test + public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() { + assertArrayEquals(new boolean[]{false, false}, + createController().arePrimitivesSupported(new int[]{ + VibrationEffect.Composition.PRIMITIVE_CLICK, + VibrationEffect.Composition.PRIMITIVE_TICK + })); + } + + @Test + public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() { + mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); + when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null); + + assertArrayEquals(new boolean[]{false, false}, + createController().arePrimitivesSupported(new int[]{ + VibrationEffect.Composition.PRIMITIVE_CLICK, + VibrationEffect.Composition.PRIMITIVE_QUICK_RISE + })); + } + + @Test + public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() { + mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); + when(mNativeWrapperMock.getSupportedPrimitives()) + .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + + assertArrayEquals(new boolean[]{true, false}, + createController().arePrimitivesSupported(new int[]{ + VibrationEffect.Composition.PRIMITIVE_CLICK, + VibrationEffect.Composition.PRIMITIVE_QUICK_RISE + })); + } + + @Test + public void setExternalControl_withCapability_enablesExternalControl() { + mockVibratorCapabilities(IVibrator.CAP_EXTERNAL_CONTROL); + VibratorController controller = createController(); + assertFalse(controller.isUnderExternalControl()); + + controller.setExternalControl(true); + assertTrue(controller.isUnderExternalControl()); + + controller.setExternalControl(false); + assertFalse(controller.isUnderExternalControl()); + + InOrder inOrderVerifier = inOrder(mNativeWrapperMock); + inOrderVerifier.verify(mNativeWrapperMock).setExternalControl(eq(true)); + inOrderVerifier.verify(mNativeWrapperMock).setExternalControl(eq(false)); + } + + @Test + public void setExternalControl_withNoCapability_ignoresExternalControl() { + VibratorController controller = createController(); + assertFalse(controller.isUnderExternalControl()); + + controller.setExternalControl(true); + assertFalse(controller.isUnderExternalControl()); + + verify(mNativeWrapperMock, never()).setExternalControl(anyBoolean()); + } + + @Test + public void updateAlwaysOn_withCapability_enablesAlwaysOnEffect() { + mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); + VibrationEffect.Prebaked effect = (VibrationEffect.Prebaked) + VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK); + createController().updateAlwaysOn(1, effect); + + verify(mNativeWrapperMock).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM)); + } + + @Test + public void updateAlwaysOn_withNullEffect_disablesAlwaysOnEffect() { + mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); + createController().updateAlwaysOn(1, null); + verify(mNativeWrapperMock).alwaysOnDisable(eq(1L)); + } + + @Test + public void updateAlwaysOn_withoutCapability_ignoresEffect() { + VibrationEffect.Prebaked effect = (VibrationEffect.Prebaked) + VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK); + createController().updateAlwaysOn(1, effect); + + verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong()); + verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + } + + @Test + public void on_withDuration_turnsVibratorOn() { + VibratorController controller = createController(); + controller.on(100, 10); + + assertTrue(controller.isVibrating()); + verify(mNativeWrapperMock).on(eq(100L), eq(10L)); + } + + @Test + public void on_withPrebaked_performsEffect() { + when(mNativeWrapperMock.perform(anyLong(), anyLong(), anyLong())).thenReturn(10L); + VibratorController controller = createController(); + + VibrationEffect.Prebaked effect = (VibrationEffect.Prebaked) + VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK); + controller.on(effect, 11); + + assertTrue(controller.isVibrating()); + verify(mNativeWrapperMock).perform(eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), eq(11L)); + } + + @Test + public void on_withComposed_performsEffect() { + mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); + VibratorController controller = createController(); + + VibrationEffect.Composed effect = (VibrationEffect.Composed) + VibrationEffect.startComposition() + .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 10) + .compose(); + controller.on(effect, 12); + + ArgumentCaptor<VibrationEffect.Composition.PrimitiveEffect[]> primitivesCaptor = + ArgumentCaptor.forClass(VibrationEffect.Composition.PrimitiveEffect[].class); + + assertTrue(controller.isVibrating()); + verify(mNativeWrapperMock).compose(primitivesCaptor.capture(), eq(12L)); + + // Check all primitive effect fields are passed down to the HAL. + assertEquals(1, primitivesCaptor.getValue().length); + VibrationEffect.Composition.PrimitiveEffect primitive = primitivesCaptor.getValue()[0]; + assertEquals(VibrationEffect.Composition.PRIMITIVE_CLICK, primitive.id); + assertEquals(0.5f, primitive.scale, /* delta= */ 1e-2); + assertEquals(10, primitive.delay); + } + + @Test + public void off_turnsOffVibrator() { + VibratorController controller = createController(); + controller.on(100, 1); + assertTrue(controller.isVibrating()); + + controller.off(); + controller.off(); + assertFalse(controller.isVibrating()); + verify(mNativeWrapperMock, times(2)).off(); + } + + @Test + public void registerVibratorStateListener_callbacksAreTriggered() throws Exception { + VibratorController controller = createController(); + + controller.registerVibratorStateListener(mVibratorStateListenerMock); + controller.on(10, 1); + controller.on(100, 2); + controller.off(); + controller.off(); + + InOrder inOrderVerifier = inOrder(mVibratorStateListenerMock); + // First notification done when listener is registered. + inOrderVerifier.verify(mVibratorStateListenerMock).onVibrating(false); + inOrderVerifier.verify(mVibratorStateListenerMock).onVibrating(eq(true)); + inOrderVerifier.verify(mVibratorStateListenerMock).onVibrating(eq(false)); + inOrderVerifier.verifyNoMoreInteractions(); + } + + @Test + public void unregisterVibratorStateListener_callbackNotTriggeredAfter() throws Exception { + VibratorController controller = createController(); + + controller.registerVibratorStateListener(mVibratorStateListenerMock); + verify(mVibratorStateListenerMock).onVibrating(false); + + controller.on(10, 1); + verify(mVibratorStateListenerMock).onVibrating(true); + + controller.unregisterVibratorStateListener(mVibratorStateListenerMock); + Mockito.clearInvocations(mVibratorStateListenerMock); + + controller.on(10, 1); + verifyNoMoreInteractions(mVibratorStateListenerMock); + } + + private void mockVibratorCapabilities(int capabilities) { + when(mNativeWrapperMock.getCapabilities()).thenReturn((long) capabilities); + } +} diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml index 7f4f3dd58812..0ed037c7e70a 100644 --- a/services/tests/wmtests/AndroidManifest.xml +++ b/services/tests/wmtests/AndroidManifest.xml @@ -65,8 +65,6 @@ android:turnScreenOn="true" /> <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ResumeWhilePausingActivity" android:resumeWhilePausing="true"/> - <activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity" - android:showWhenLocked="true" android:allowEmbedded="true"/> <activity android:name="com.android.server.wm.ActivityLeakTests$DetectLeakActivity" /> </application> diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index bded3f9de9ba..565bf8b615c7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -422,7 +422,7 @@ public class ActivityStarterTests extends WindowTestsBase { // verify that values are passed to the modifier. Values are passed thrice -- two for // setting initial state, another when task is created. verify(modifier, times(3)).onCalculate(any(), eq(windowLayout), any(), any(), eq(options), - anyInt(), any(), any()); + anyInt(), any(), any(), any()); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java index 017ed883e2bd..475e462bdd3d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java @@ -34,6 +34,7 @@ import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.timeout; import android.app.WaitResult; import android.content.pm.ActivityInfo; @@ -45,6 +46,8 @@ import androidx.test.filters.MediumTest; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.concurrent.TimeUnit; + /** * Tests for the {@link ActivityTaskSupervisor} class. * @@ -190,4 +193,16 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase { assertThat(allowedOnUntrusted).isFalse(); } + + /** + * We need to launch home again after user unlocked for those displays that do not have + * encryption aware home app. + */ + @Test + public void testStartHomeAfterUserUnlocked() { + mSupervisor.onUserUnlocked(0); + waitHandlerIdle(mAtm.mH); + verify(mRootWindowContainer, timeout(TimeUnit.SECONDS.toMillis(10))) + .startHomeOnEmptyDisplays("userUnlocked"); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index 21bdc9e7785e..79b2da187680 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -236,8 +236,7 @@ public class DisplayPolicyTests extends WindowTestsBase { final WindowState activity = createBaseApplicationWindow(); activity.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; - policy.adjustWindowParamsLw(activity, activity.mAttrs, 0 /* callingPid */, - 0 /* callingUid */); + policy.adjustWindowParamsLw(activity, activity.mAttrs); } private WindowState createApplicationWindow() { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java index 94ffcdab4fa7..20775e84fd8f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java @@ -107,11 +107,9 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { } void addWindow(WindowState win) { - final int callingPid = Binder.getCallingPid(); - final int callingUid = Binder.getCallingUid(); - mDisplayPolicy.adjustWindowParamsLw(win, win.mAttrs, callingPid, callingUid); - assertEquals(WindowManagerGlobal.ADD_OKAY, - mDisplayPolicy.validateAddingWindowLw(win.mAttrs, callingPid, callingUid)); + mDisplayPolicy.adjustWindowParamsLw(win, win.mAttrs); + assertEquals(WindowManagerGlobal.ADD_OKAY, mDisplayPolicy.validateAddingWindowLw( + win.mAttrs, Binder.getCallingPid(), Binder.getCallingUid())); mDisplayPolicy.addWindowLw(win, win.mAttrs); win.mHasSurface = true; } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java index b346bb810b2e..eaedd58001c1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; @@ -167,7 +168,7 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { mBaseSettingsStorage, mOverrideSettingsStorage); SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); overrideSettings.mShouldShowSystemDecors = true; - overrideSettings.mShouldShowIme = true; + overrideSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); @@ -176,8 +177,8 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { getStoredDisplayAttributeValue(mOverrideSettingsStorage, "name")); assertEquals("Attribute value must be stored", "true", getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowSystemDecors")); - assertEquals("Attribute value must be stored", "true", - getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowIme")); + assertEquals("Attribute value must be stored", "0", + getStoredDisplayAttributeValue(mOverrideSettingsStorage, "imePolicy")); } @Test @@ -195,7 +196,7 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { mBaseSettingsStorage, mOverrideSettingsStorage); SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo); overrideSettings.mShouldShowSystemDecors = true; - overrideSettings.mShouldShowIme = true; + overrideSettings.mImePolicy = DISPLAY_IME_POLICY_LOCAL; provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings); assertTrue(mOverrideSettingsStorage.wasWriteSuccessful()); @@ -204,8 +205,8 @@ public class DisplayWindowSettingsProviderTests extends WindowTestsBase { getStoredDisplayAttributeValue(mOverrideSettingsStorage, "name")); assertEquals("Attribute value must be stored", "true", getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowSystemDecors")); - assertEquals("Attribute value must be stored", "true", - getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowIme")); + assertEquals("Attribute value must be stored", "0", + getStoredDisplayAttributeValue(mOverrideSettingsStorage, "imePolicy")); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java index 2ca5583c48c3..9e4cd161c478 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java @@ -22,6 +22,8 @@ import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DISABLED; import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_ENABLED; import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY; import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; @@ -49,7 +51,6 @@ import androidx.test.filters.SmallTest; import com.android.server.LocalServices; import com.android.server.policy.WindowManagerPolicy; -import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry; import org.junit.Before; import org.junit.Test; @@ -319,17 +320,21 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { } @Test - public void testPrimaryDisplayShouldShowIme() { - assertTrue(mDisplayWindowSettings.shouldShowImeLocked(mPrimaryDisplay)); + public void testPrimaryDisplayImePolicy() { + assertEquals(DISPLAY_IME_POLICY_LOCAL, + mDisplayWindowSettings.getImePolicyLocked(mPrimaryDisplay)); - mDisplayWindowSettings.setShouldShowImeLocked(mPrimaryDisplay, false); + mDisplayWindowSettings.setDisplayImePolicy(mPrimaryDisplay, + DISPLAY_IME_POLICY_FALLBACK_DISPLAY); - assertTrue(mDisplayWindowSettings.shouldShowImeLocked(mPrimaryDisplay)); + assertEquals(DISPLAY_IME_POLICY_LOCAL, + mDisplayWindowSettings.getImePolicyLocked(mPrimaryDisplay)); } @Test - public void testSecondaryDisplayDefaultToNotShowIme() { - assertFalse(mDisplayWindowSettings.shouldShowImeLocked(mSecondaryDisplay)); + public void testSecondaryDisplayDefaultToShowImeOnFallbackDisplay() { + assertEquals(DISPLAY_IME_POLICY_FALLBACK_DISPLAY, + mDisplayWindowSettings.getImePolicyLocked(mSecondaryDisplay)); } @Test @@ -400,17 +405,18 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { } @Test - public void testShouldShowImeWithinForceDesktopMode() { + public void testShouldShowImeOnDisplayWithinForceDesktopMode() { try { // Presume display enabled force desktop mode from developer options. final DisplayContent dc = createMockSimulatedDisplay(); mWm.setForceDesktopModeOnExternalDisplays(true); final WindowManagerInternal wmInternal = LocalServices.getService( WindowManagerInternal.class); - // Make sure WindowManagerInter#shouldShowIme as true is due to - // mForceDesktopModeOnExternalDisplays as true. - assertFalse(mWm.mDisplayWindowSettings.shouldShowImeLocked(dc)); - assertTrue(wmInternal.shouldShowIme(dc.getDisplayId())); + // Make sure WindowManagerInter#getDisplayImePolicy is SHOW_IME_ON_DISPLAY is due to + // mForceDesktopModeOnExternalDisplays being SHOW_IME_ON_DISPLAY. + assertEquals(DISPLAY_IME_POLICY_FALLBACK_DISPLAY, + mWm.mDisplayWindowSettings.getImePolicyLocked(dc)); + assertEquals(DISPLAY_IME_POLICY_LOCAL, wmInternal.getDisplayImePolicy(dc.getDisplayId())); } finally { mWm.setForceDesktopModeOnExternalDisplays(false); } diff --git a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java index a9f6b50d4be5..f75c98f39323 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java @@ -18,14 +18,28 @@ package com.android.server.wm; import static android.view.Display.DEFAULT_DISPLAY; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; + import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import android.content.Context; +import android.content.res.Resources; import android.graphics.Rect; +import android.hardware.display.DisplayManagerGlobal; +import android.os.IBinder; import android.platform.test.annotations.Presubmit; +import android.view.Display; +import android.view.IWindowManager; import android.view.WindowManager; +import android.view.WindowManagerGlobal; import com.android.server.inputmethod.InputMethodManagerService; import com.android.server.inputmethod.InputMethodMenuController; @@ -45,10 +59,34 @@ import org.junit.runner.RunWith; public class InputMethodMenuControllerTest extends WindowTestsBase { private InputMethodMenuController mController; + private TestDisplayContent mSecondaryDisplay; @Before - public void setUp() { + public void setUp() throws Exception { mController = new InputMethodMenuController(mock(InputMethodManagerService.class)); + + // Mock addWindowTokenWithOptions to create a test window token. + IWindowManager wms = WindowManagerGlobal.getWindowManagerService(); + spyOn(wms); + doAnswer(invocation -> { + Object[] args = invocation.getArguments(); + final IBinder token = (IBinder) args[0]; + final int windowType = (int) args[1]; + new WindowToken(mWm, token, windowType, true /* persistOnEmpty */, + mDefaultDisplay, true /* ownerCanManageAppTokens */, 1000 /* ownerUid */, + false /* roundedCornerOverlay */, true /* fromClientToken */); + return WindowManagerGlobal.ADD_OKAY; + }).when(wms).addWindowTokenWithOptions(any(), anyInt(), anyInt(), any(), anyString()); + + mSecondaryDisplay = new TestDisplayContent.Builder(mAtm, 1000, 1000).build(); + + // Mock DisplayManagerGlobal to return test display when obtaining Display instance. + final int displayId = mSecondaryDisplay.getDisplayId(); + final Display display = mSecondaryDisplay.getDisplay(); + DisplayManagerGlobal displayManagerGlobal = DisplayManagerGlobal.getInstance(); + spyOn(displayManagerGlobal); + doReturn(display).when(displayManagerGlobal).getCompatibleDisplay(eq(displayId), + (Resources) any()); } @Test @@ -60,9 +98,9 @@ public class InputMethodMenuControllerTest extends WindowTestsBase { // Obtain the context again and check they are the same instance and match the display // metrics of the secondary display. final Context contextOnSecondaryDisplay = mController.getSettingsContext( - mDisplayContent.getDisplayId()); + mSecondaryDisplay.getDisplayId()); - assertImeSwitchContextMetricsValidity(contextOnSecondaryDisplay, mDisplayContent); + assertImeSwitchContextMetricsValidity(contextOnSecondaryDisplay, mSecondaryDisplay); assertThat(contextOnDefaultDisplay.getWindowContextToken()) .isEqualTo(contextOnSecondaryDisplay.getWindowContextToken()); } diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java index e514ac04efbe..cd428e10a437 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java @@ -33,6 +33,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.ActivityStarter.Request; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_DONE; @@ -92,11 +93,12 @@ public class LaunchParamsControllerTests extends WindowTestsBase { final ActivityRecord source = new ActivityBuilder(mAtm).build(); final WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0); final ActivityOptions options = mock(ActivityOptions.class); + final Request request = new Request(); mController.calculate(record.getTask(), layout, record, source, options, PHASE_BOUNDS, - new LaunchParams()); + new LaunchParams(), request); verify(positioner, times(1)).onCalculate(eq(record.getTask()), eq(layout), eq(record), - eq(source), eq(options), anyInt(), any(), any()); + eq(source), eq(options), anyInt(), any(), any(), eq(request)); } /** @@ -119,9 +121,9 @@ public class LaunchParamsControllerTests extends WindowTestsBase { mPersister.putLaunchParams(userId, name, expected); mController.calculate(activity.getTask(), null /*layout*/, activity, null /*source*/, - null /*options*/, PHASE_BOUNDS, new LaunchParams()); + null /*options*/, PHASE_BOUNDS, new LaunchParams(), null /* request */); verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(), - eq(expected), any()); + eq(expected), any(), any()); } /** @@ -132,16 +134,17 @@ public class LaunchParamsControllerTests extends WindowTestsBase { final LaunchParamsModifier ignoredPositioner = mock(LaunchParamsModifier.class); final LaunchParamsModifier earlyExitPositioner = - (task, layout, activity, source, options, phase, currentParams, outParams) + (task, layout, activity, source, options, phase, currentParams, outParams, request) -> RESULT_DONE; mController.registerModifier(ignoredPositioner); mController.registerModifier(earlyExitPositioner); mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, - null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams()); + null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(), + null /* request */); verify(ignoredPositioner, never()).onCalculate(any(), any(), any(), any(), any(), anyInt(), - any(), any()); + any(), any(), any()); } /** @@ -157,20 +160,22 @@ public class LaunchParamsControllerTests extends WindowTestsBase { mController.registerModifier(firstPositioner); mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, - null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams()); + null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(), + null /* request */); verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(), - any(), any()); + any(), any(), any()); final LaunchParamsModifier secondPositioner = spy(earlyExitPositioner); mController.registerModifier(secondPositioner); mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, - null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams()); + null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(), + null /* request */); verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(), - any(), any()); + any(), any(), any()); verify(secondPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(), - any(), any()); + any(), any(), any()); } /** @@ -192,10 +197,10 @@ public class LaunchParamsControllerTests extends WindowTestsBase { mController.registerModifier(positioner2); mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/, - null /*options*/, PHASE_BOUNDS, new LaunchParams()); + null /*options*/, PHASE_BOUNDS, new LaunchParams(), null /* request */); verify(positioner1, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(), - eq(positioner2.getLaunchParams()), any()); + eq(positioner2.getLaunchParams()), any(), any()); } /** @@ -218,7 +223,7 @@ public class LaunchParamsControllerTests extends WindowTestsBase { final LaunchParams result = new LaunchParams(); mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/, - null /*options*/, PHASE_BOUNDS, result); + null /*options*/, PHASE_BOUNDS, result, null /* request */); assertEquals(result, positioner2.getLaunchParams()); } @@ -237,17 +242,17 @@ public class LaunchParamsControllerTests extends WindowTestsBase { // VR activities should always land on default display. mController.calculate(null /*task*/, null /*layout*/, vrActivity /*activity*/, - null /*source*/, null /*options*/, PHASE_BOUNDS, result); + null /*source*/, null /*options*/, PHASE_BOUNDS, result, null /* request */); assertEquals(mRootWindowContainer.getDefaultTaskDisplayArea(), result.mPreferredTaskDisplayArea); // Otherwise, always lands on VR 2D display. final ActivityRecord vr2dActivity = new ActivityBuilder(mAtm).build(); mController.calculate(null /*task*/, null /*layout*/, vr2dActivity /*activity*/, - null /*source*/, null /*options*/, PHASE_BOUNDS, result); + null /*source*/, null /*options*/, PHASE_BOUNDS, result, null /* request */); assertEquals(vrDisplay.getDefaultTaskDisplayArea(), result.mPreferredTaskDisplayArea); mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/, - null /*options*/, PHASE_BOUNDS, result); + null /*options*/, PHASE_BOUNDS, result, null /* request */); assertEquals(vrDisplay.getDefaultTaskDisplayArea(), result.mPreferredTaskDisplayArea); mAtm.mVr2dDisplayId = INVALID_DISPLAY; @@ -269,9 +274,9 @@ public class LaunchParamsControllerTests extends WindowTestsBase { final ActivityOptions options = mock(ActivityOptions.class); mController.calculate(record.getTask(), layout, record, source, options, PHASE_BOUNDS, - new LaunchParams()); + new LaunchParams(), null /* request */); verify(positioner, times(1)).onCalculate(eq(record.getTask()), eq(layout), eq(record), - eq(source), eq(options), eq(PHASE_BOUNDS), any(), any()); + eq(source), eq(options), eq(PHASE_BOUNDS), any(), any(), any()); } /** @@ -403,8 +408,9 @@ public class LaunchParamsControllerTests extends WindowTestsBase { @Override public int onCalculate(Task task, WindowLayout layout, ActivityRecord activity, - ActivityRecord source, ActivityOptions options, int phase, - LaunchParams currentParams, LaunchParams outParams) { + ActivityRecord source, ActivityOptions options, int phase, + LaunchParams currentParams, LaunchParams outParams, + Request request) { outParams.set(mParams); return mReturnVal; } diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java deleted file mode 100644 index 25ba6db38e05..000000000000 --- a/services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -import static android.graphics.Color.RED; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; -import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.Gravity.BOTTOM; -import static android.view.Gravity.LEFT; -import static android.view.Gravity.RIGHT; -import static android.view.Gravity.TOP; -import static android.view.InsetsState.ITYPE_CLIMATE_BAR; -import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; -import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; - -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertEquals; - -import android.app.Activity; -import android.app.ActivityOptions; -import android.app.Instrumentation; -import android.content.Context; -import android.content.Intent; -import android.graphics.PixelFormat; -import android.graphics.Point; -import android.hardware.display.DisplayManager; -import android.hardware.display.VirtualDisplay; -import android.media.ImageReader; -import android.os.Handler; -import android.os.SystemClock; -import android.platform.test.annotations.Presubmit; -import android.util.Pair; -import android.view.Display; -import android.view.DisplayInfo; -import android.view.View; -import android.view.WindowInsets; -import android.view.WindowManager; -import android.widget.TextView; - -import androidx.test.filters.SmallTest; - -import com.android.compatibility.common.util.SystemUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.function.BooleanSupplier; - -/** - * Tests for the {@link android.view.WindowManager.LayoutParams#PRIVATE_FLAG_IS_SCREEN_DECOR} flag. - * - * Build/Install/Run: - * atest WmTests:ScreenDecorWindowTests - */ -// TODO: Add test for FLAG_FULLSCREEN which hides the status bar and also other flags. -// TODO: Test non-Activity windows. -@SmallTest -@Presubmit -public class ScreenDecorWindowTests { - - private final Context mContext = getInstrumentation().getTargetContext(); - private final Instrumentation mInstrumentation = getInstrumentation(); - - private WindowManager mWm; - private ArrayList<View> mWindows = new ArrayList<>(); - - private Activity mTestActivity; - private VirtualDisplay mDisplay; - private ImageReader mImageReader; - - private int mDecorThickness; - private int mHalfDecorThickness; - - @Before - public void setUp() { - final Pair<VirtualDisplay, ImageReader> result = createDisplay(); - mDisplay = result.first; - mImageReader = result.second; - final Display display = mDisplay.getDisplay(); - final Context dContext = mContext.createDisplayContext(display); - mWm = dContext.getSystemService(WindowManager.class); - mTestActivity = startActivityOnDisplay(TestActivity.class, display.getDisplayId()); - final Point size = new Point(); - mDisplay.getDisplay().getRealSize(size); - mDecorThickness = Math.min(size.x, size.y) / 3; - mHalfDecorThickness = mDecorThickness / 2; - } - - @After - public void tearDown() { - while (!mWindows.isEmpty()) { - removeWindow(mWindows.get(0)); - } - finishActivity(mTestActivity); - mDisplay.release(); - mImageReader.close(); - } - - @Test - public void testScreenSides() { - // Decor on top - final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - - // Decor at the bottom - updateWindow(decorWindow, BOTTOM, MATCH_PARENT, mDecorThickness, 0, 0); - assertInsetGreaterOrEqual(mTestActivity, BOTTOM, mDecorThickness); - - // Decor to the left - updateWindow(decorWindow, LEFT, mDecorThickness, MATCH_PARENT, 0, 0); - assertInsetGreaterOrEqual(mTestActivity, LEFT, mDecorThickness); - - // Decor to the right - updateWindow(decorWindow, RIGHT, mDecorThickness, MATCH_PARENT, 0, 0); - assertInsetGreaterOrEqual(mTestActivity, RIGHT, mDecorThickness); - } - - // Decor windows (i.e windows using PRIVATE_FLAG_IS_SCREEN_DECOR) are no longer supported. - // PRIVATE_FLAG_IS_SCREEN_DECOR and related code will be deprecated/removed soon. - @Ignore - @Test - public void testMultipleDecors() { - // Test 2 decor windows on-top. - createDecorWindow(TOP, MATCH_PARENT, mHalfDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mHalfDecorThickness); - createDecorWindow(TOP, MATCH_PARENT, mDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - - // And one at the bottom. - createDecorWindow(BOTTOM, MATCH_PARENT, mHalfDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, BOTTOM, mHalfDecorThickness); - } - - @Test - public void testFlagChange() { - WindowInsets initialInsets = getInsets(mTestActivity); - - final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness); - assertTopInsetEquals(mTestActivity, mDecorThickness); - - updateWindow(decorWindow, TOP, MATCH_PARENT, mDecorThickness, - 0, PRIVATE_FLAG_IS_SCREEN_DECOR); - - // TODO: fix test and re-enable assertion. - // initialInsets was not actually immutable and just updated to the current insets, - // meaning this assertion never actually tested anything. Now that WindowInsets actually is - // immutable, it turns out the test was broken. - // assertTopInsetEquals(mTestActivity, initialInsets.getSystemWindowInsetTop()); - - updateWindow(decorWindow, TOP, MATCH_PARENT, mDecorThickness, - PRIVATE_FLAG_IS_SCREEN_DECOR, PRIVATE_FLAG_IS_SCREEN_DECOR); - assertTopInsetEquals(mTestActivity, mDecorThickness); - } - - @Test - public void testRemoval() { - WindowInsets initialInsets = getInsets(mTestActivity); - - final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - - removeWindow(decorWindow); - assertTopInsetEquals(mTestActivity, initialInsets.getSystemWindowInsetTop()); - } - - @Test - public void testProvidesInsetsTypes() { - int[] providesInsetsTypes = new int[]{ITYPE_CLIMATE_BAR}; - final View win = createWindow("StatusBarSubPanel", TOP, MATCH_PARENT, mDecorThickness, RED, - FLAG_LAYOUT_IN_SCREEN, 0, providesInsetsTypes); - - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - } - - private View createDecorWindow(int gravity, int width, int height) { - int[] providesInsetsTypes = - new int[]{gravity == TOP ? ITYPE_CLIMATE_BAR : ITYPE_EXTRA_NAVIGATION_BAR}; - return createWindow("decorWindow", gravity, width, height, RED, - FLAG_LAYOUT_IN_SCREEN, PRIVATE_FLAG_IS_SCREEN_DECOR, providesInsetsTypes); - } - - private View createWindow(String name, int gravity, int width, int height, int color, int flags, - int privateFlags, int[] providesInsetsTypes) { - - final View[] viewHolder = new View[1]; - final int finalFlag = flags - | FLAG_NOT_FOCUSABLE | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_NOT_TOUCHABLE; - - // Needs to run on the UI thread. - Handler.getMain().runWithScissors(() -> { - final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - width, height, TYPE_APPLICATION_OVERLAY, finalFlag, PixelFormat.OPAQUE); - lp.gravity = gravity; - lp.privateFlags |= privateFlags; - lp.providesInsetsTypes = providesInsetsTypes; - - final TextView view = new TextView(mContext); - view.setText("ScreenDecorWindowTests - " + name); - view.setBackgroundColor(color); - mWm.addView(view, lp); - mWindows.add(view); - viewHolder[0] = view; - }, 0); - - waitForIdle(); - return viewHolder[0]; - } - - private void updateWindow(View v, int gravity, int width, int height, - int privateFlags, int privateFlagsMask) { - // Needs to run on the UI thread. - Handler.getMain().runWithScissors(() -> { - final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) v.getLayoutParams(); - lp.gravity = gravity; - lp.width = width; - lp.height = height; - setPrivateFlags(lp, privateFlags, privateFlagsMask); - - mWm.updateViewLayout(v, lp); - }, 0); - - waitForIdle(); - } - - private void removeWindow(View v) { - Handler.getMain().runWithScissors(() -> mWm.removeView(v), 0); - mWindows.remove(v); - waitForIdle(); - } - - private WindowInsets getInsets(Activity a) { - return new WindowInsets(a.getWindow().getDecorView().getRootWindowInsets()); - } - - /** - * Set the flags of the window, as per the - * {@link WindowManager.LayoutParams WindowManager.LayoutParams} - * flags. - * - * @param flags The new window flags (see WindowManager.LayoutParams). - * @param mask Which of the window flag bits to modify. - */ - public void setPrivateFlags(WindowManager.LayoutParams lp, int flags, int mask) { - lp.flags = (lp.flags & ~mask) | (flags & mask); - } - - /** - * Asserts the top inset of {@param activity} is equal to {@param expected} waiting as needed. - */ - private void assertTopInsetEquals(Activity activity, int expected) { - waitForTopInsetEqual(activity, expected); - assertEquals(expected, getInsets(activity).getSystemWindowInsetTop()); - } - - private void waitForTopInsetEqual(Activity activity, int expected) { - waitFor(() -> getInsets(activity).getSystemWindowInsetTop() == expected); - } - - /** - * Asserts the inset at {@param side} of {@param activity} is equal to {@param expected} - * waiting as needed. - */ - private void assertInsetGreaterOrEqual(Activity activity, int side, int expected) { - waitForInsetGreaterOrEqual(activity, side, expected); - - final WindowInsets insets = getInsets(activity); - switch (side) { - case TOP: - assertThat(insets.getSystemWindowInsetTop()).isAtLeast(expected); - break; - case BOTTOM: - assertThat(insets.getSystemWindowInsetBottom()).isAtLeast(expected); - break; - case LEFT: - assertThat(insets.getSystemWindowInsetLeft()).isAtLeast(expected); - break; - case RIGHT: - assertThat(insets.getSystemWindowInsetRight()).isAtLeast(expected); - break; - } - } - - private void waitForInsetGreaterOrEqual(Activity activity, int side, int expected) { - waitFor(() -> { - final WindowInsets insets = getInsets(activity); - switch (side) { - case TOP: return insets.getSystemWindowInsetTop() >= expected; - case BOTTOM: return insets.getSystemWindowInsetBottom() >= expected; - case LEFT: return insets.getSystemWindowInsetLeft() >= expected; - case RIGHT: return insets.getSystemWindowInsetRight() >= expected; - default: return true; - } - }); - } - - private void waitFor(BooleanSupplier waitCondition) { - int retriesLeft = 5; - do { - if (waitCondition.getAsBoolean()) { - break; - } - SystemClock.sleep(500); - } while (retriesLeft-- > 0); - } - - private void finishActivity(Activity a) { - if (a == null) { - return; - } - a.finish(); - waitForIdle(); - } - - private void waitForIdle() { - mInstrumentation.waitForIdleSync(); - } - - private Activity startActivityOnDisplay(Class<?> cls, int displayId) { - final Intent intent = new Intent(mContext, cls); - intent.addFlags(FLAG_ACTIVITY_NEW_TASK); - final ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchDisplayId(displayId); - - final Activity activity = SystemUtil.runWithShellPermissionIdentity( - () -> mInstrumentation.startActivitySync(intent, options.toBundle()), - "android.permission.ACTIVITY_EMBEDDING"); - waitForIdle(); - - assertEquals(displayId, activity.getDisplayId()); - return activity; - } - - private Pair<VirtualDisplay, ImageReader> createDisplay() { - final DisplayManager dm = mContext.getSystemService(DisplayManager.class); - final DisplayInfo displayInfo = new DisplayInfo(); - final Display defaultDisplay = dm.getDisplay(DEFAULT_DISPLAY); - defaultDisplay.getDisplayInfo(displayInfo); - final String name = "ScreenDecorWindowTests"; - int flags = VIRTUAL_DISPLAY_FLAG_PRESENTATION | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; - - final ImageReader imageReader = ImageReader.newInstance( - displayInfo.logicalWidth, displayInfo.logicalHeight, PixelFormat.RGBA_8888, 2); - - final VirtualDisplay display = dm.createVirtualDisplay(name, displayInfo.logicalWidth, - displayInfo.logicalHeight, displayInfo.logicalDensityDpi, imageReader.getSurface(), - flags); - - return Pair.create(display, imageReader); - } - - public static class TestActivity extends Activity { - } -} diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index 98520bb7a20b..4f55322e2085 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -35,6 +35,7 @@ import static android.view.InsetsState.ITYPE_STATUS_BAR; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.server.wm.ActivityStarter.Request; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE; import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP; @@ -42,6 +43,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import android.app.ActivityOptions; import android.content.pm.ActivityInfo; @@ -265,6 +269,180 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { mResult.mPreferredTaskDisplayArea); } + @Test + public void testUsesDisplayAreaFromTopMostActivityInApplicationIfAvailable() { + final String processName = "processName"; + final int uid = 124214; + final TestDisplayContent firstScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN); + final TestDisplayContent secondScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN); + final TaskDisplayArea expectedDisplayArea = secondScreen.getDefaultTaskDisplayArea(); + final WindowProcessController controller = mock(WindowProcessController.class); + + when(controller.getTopActivityDisplayArea()).thenReturn(expectedDisplayArea); + + when(mActivity.getProcessName()).thenReturn(processName); + when(mActivity.getUid()).thenReturn(uid); + doReturn(controller) + .when(mSupervisor.mService) + .getProcessController(processName, uid); + + assertEquals(RESULT_CONTINUE, mTarget.onCalculate( + null /* task */, + null /* layout */, + mActivity /* activity */, + null /* source */, + null /* options */, + -1 /* phase */, + mCurrent, + mResult, + null /* request */ + )); + + assertEquals(expectedDisplayArea, mResult.mPreferredTaskDisplayArea); + } + + @Test + public void testUsesDisplayAreaFromLaunchingActivityIfApplicationLaunching() { + final String processName = "processName"; + final int uid = 124214; + final TestDisplayContent firstScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN); + final TestDisplayContent secondScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN); + final TaskDisplayArea expectedTaskDisplayArea = secondScreen.getDefaultTaskDisplayArea(); + final WindowProcessController controller = mock(WindowProcessController.class); + + when(controller.getTopActivityDisplayArea()).thenReturn(expectedTaskDisplayArea); + + when(mActivity.getProcessName()).thenReturn(processName); + when(mActivity.getUid()).thenReturn(uid); + doReturn(null) + .when(mSupervisor.mService) + .getProcessController(processName, uid); + + doReturn(controller) + .when(mSupervisor.mService) + .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid); + + assertEquals(RESULT_CONTINUE, mTarget.onCalculate( + null /* task */, + null /* layout */, + mActivity /* activity */, + null /* source */, + null /* options */, + -1 /* phase */, + mCurrent, + mResult, + null /* request */ + )); + + assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea); + } + + @Test + public void testDisplayAreaFromLaunchingActivityTakesPrecedence() { + final String processName = "processName"; + final int uid = 124214; + final TestDisplayContent firstScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN); + final TestDisplayContent secondScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN); + final TaskDisplayArea firstTaskDisplayArea = firstScreen.getDefaultTaskDisplayArea(); + final TaskDisplayArea expectedTaskDisplayArea = secondScreen.getDefaultTaskDisplayArea(); + final WindowProcessController controllerForLaunching = mock(WindowProcessController.class); + final WindowProcessController controllerForApplication = + mock(WindowProcessController.class); + + when(mActivity.getProcessName()).thenReturn(processName); + when(mActivity.getUid()).thenReturn(uid); + + when(controllerForApplication.getTopActivityDisplayArea()).thenReturn(firstTaskDisplayArea); + when(controllerForLaunching.getTopActivityDisplayArea()) + .thenReturn(expectedTaskDisplayArea); + + doReturn(controllerForApplication) + .when(mSupervisor.mService) + .getProcessController(processName, uid); + doReturn(controllerForLaunching) + .when(mSupervisor.mService) + .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid); + + assertEquals(RESULT_CONTINUE, mTarget.onCalculate( + null /* task */, + null /* layout */, + mActivity /* activity */, + null /* source */, + null /* options */, + -1 /* phase */, + mCurrent, + mResult, + null /* request */ + )); + + assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea); + } + + @Test + public void testUsesDisplayAreaOriginalProcessAsLastResort() { + final TestDisplayContent firstScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN); + final TestDisplayContent secondScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN); + final TaskDisplayArea expectedTaskDisplayArea = secondScreen.getDefaultTaskDisplayArea(); + final Request request = new Request(); + request.realCallingPid = 12412413; + request.realCallingUid = 235424; + + final WindowProcessController controller = mock(WindowProcessController.class); + + when(controller.getTopActivityDisplayArea()).thenReturn(expectedTaskDisplayArea); + + doReturn(null) + .when(mSupervisor.mService) + .getProcessController(mActivity.processName, mActivity.info.applicationInfo.uid); + + doReturn(null) + .when(mSupervisor.mService) + .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid); + + doReturn(controller) + .when(mSupervisor.mService) + .getProcessController(request.realCallingPid, request.realCallingUid); + + assertEquals(RESULT_CONTINUE, mTarget.onCalculate( + null /* task */, + null /* layout */, + mActivity /* activity */, + null /* source */, + null /* options */, + -1 /* phase */, + mCurrent, + mResult, + request + )); + + assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea); + } + + @Test + public void testUsesDefaultDisplayAreaIfWindowProcessControllerIsNotPresent() { + doReturn(null) + .when(mSupervisor.mService) + .getProcessController(mActivity.processName, mActivity.info.applicationInfo.uid); + + doReturn(null) + .when(mSupervisor.mService) + .getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid); + + assertEquals(RESULT_CONTINUE, mTarget.onCalculate( + null /* task */, + null /* layout */, + mActivity /* activity */, + null /* source */, + null /* options */, + -1 /* phase */, + mCurrent, + mResult, + null /* request */ + )); + + assertEquals(DEFAULT_DISPLAY, mResult.mPreferredTaskDisplayArea.getDisplayId()); + } + // ===================================== // Launch Windowing Mode Related Tests // ===================================== diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 165d4681c9e0..4909b1d7629e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; import static android.window.TransitionInfo.TRANSIT_HIDE; @@ -46,16 +47,24 @@ import org.junit.runner.RunWith; @RunWith(WindowTestRunner.class) public class TransitionTests extends WindowTestsBase { + private Transition createTestTransition(int transitType) { + TransitionController controller = mock(TransitionController.class); + BLASTSyncEngine sync = new BLASTSyncEngine(mWm); + return new Transition(transitType, 0 /* flags */, controller, sync); + } + @Test public void testCreateInfo_NewTask() { + final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN); + ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges; + ArraySet<WindowContainer> participants = transition.mParticipants; + final Task newTask = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent); final Task oldTask = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent); final ActivityRecord closing = createActivityRecord(oldTask); final ActivityRecord opening = createActivityRecord(newTask); - ArrayMap<WindowContainer, Transition.ChangeInfo> changes = new ArrayMap<>(); - ArraySet<WindowContainer> participants = new ArraySet(); // Start states. changes.put(newTask, new Transition.ChangeInfo(false /* vis */, true /* exChg */)); changes.put(oldTask, new Transition.ChangeInfo(true /* vis */, true /* exChg */)); @@ -70,29 +79,32 @@ public class TransitionTests extends WindowTestsBase { // Check basic both tasks participating participants.add(oldTask); participants.add(newTask); - TransitionInfo info = - Transition.calculateTransitionInfo(transitType, participants, changes); + ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes); + TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(2, info.getChanges().size()); assertEquals(transitType, info.getType()); // Check that children are pruned participants.add(opening); participants.add(closing); - info = Transition.calculateTransitionInfo(transitType, participants, changes); + targets = Transition.calculateTargets(participants, changes); + info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); // Check combined prune and promote participants.remove(newTask); - info = Transition.calculateTransitionInfo(transitType, participants, changes); + targets = Transition.calculateTargets(participants, changes); + info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); // Check multi promote participants.remove(oldTask); - info = Transition.calculateTransitionInfo(transitType, participants, changes); + targets = Transition.calculateTargets(participants, changes); + info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); @@ -100,6 +112,10 @@ public class TransitionTests extends WindowTestsBase { @Test public void testCreateInfo_NestedTasks() { + final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN); + ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges; + ArraySet<WindowContainer> participants = transition.mParticipants; + final Task newTask = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent); final Task newNestedTask = createTaskInStack(newTask, 0); @@ -109,8 +125,6 @@ public class TransitionTests extends WindowTestsBase { final ActivityRecord closing = createActivityRecord(oldTask); final ActivityRecord opening = createActivityRecord(newNestedTask); final ActivityRecord opening2 = createActivityRecord(newNestedTask2); - ArrayMap<WindowContainer, Transition.ChangeInfo> changes = new ArrayMap<>(); - ArraySet<WindowContainer> participants = new ArraySet(); // Start states. changes.put(newTask, new Transition.ChangeInfo(false /* vis */, true /* exChg */)); changes.put(newNestedTask, new Transition.ChangeInfo(false /* vis */, true /* exChg */)); @@ -130,8 +144,8 @@ public class TransitionTests extends WindowTestsBase { participants.add(oldTask); participants.add(opening); participants.add(opening2); - TransitionInfo info = - Transition.calculateTransitionInfo(transitType, participants, changes); + ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes); + TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(2, info.getChanges().size()); assertEquals(transitType, info.getType()); assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken())); @@ -139,7 +153,8 @@ public class TransitionTests extends WindowTestsBase { // Check that unchanging but visible descendant of sibling prevents promotion participants.remove(opening2); - info = Transition.calculateTransitionInfo(transitType, participants, changes); + targets = Transition.calculateTargets(participants, changes); + info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(newNestedTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); @@ -147,6 +162,9 @@ public class TransitionTests extends WindowTestsBase { @Test public void testCreateInfo_DisplayArea() { + final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN); + ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges; + ArraySet<WindowContainer> participants = transition.mParticipants; final Task showTask = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent); final Task showNestedTask = createTaskInStack(showTask, 0); @@ -155,8 +173,6 @@ public class TransitionTests extends WindowTestsBase { final DisplayArea tda = showTask.getDisplayArea(); final ActivityRecord showing = createActivityRecord(showNestedTask); final ActivityRecord showing2 = createActivityRecord(showTask2); - ArrayMap<WindowContainer, Transition.ChangeInfo> changes = new ArrayMap<>(); - ArraySet<WindowContainer> participants = new ArraySet(); // Start states. changes.put(showTask, new Transition.ChangeInfo(false /* vis */, true /* exChg */)); changes.put(showNestedTask, new Transition.ChangeInfo(false /* vis */, true /* exChg */)); @@ -173,8 +189,8 @@ public class TransitionTests extends WindowTestsBase { // Check promotion to DisplayArea participants.add(showing); participants.add(showing2); - TransitionInfo info = - Transition.calculateTransitionInfo(transitType, participants, changes); + ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes); + TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(1, info.getChanges().size()); assertEquals(transitType, info.getType()); assertNotNull(info.getChange(tda.mRemoteToken.toWindowContainerToken())); @@ -182,22 +198,21 @@ public class TransitionTests extends WindowTestsBase { ITaskOrganizer mockOrg = mock(ITaskOrganizer.class); // Check that organized tasks get reported even if not top showTask.mTaskOrganizer = mockOrg; - info = Transition.calculateTransitionInfo(transitType, participants, changes); + targets = Transition.calculateTargets(participants, changes); + info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(tda.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(showTask.mRemoteToken.toWindowContainerToken())); // Even if DisplayArea explicitly participating participants.add(tda); - info = Transition.calculateTransitionInfo(transitType, participants, changes); + targets = Transition.calculateTargets(participants, changes); + info = Transition.calculateTransitionInfo(transitType, targets, changes); assertEquals(2, info.getChanges().size()); } @Test public void testCreateInfo_existenceChange() { - TransitionController controller = mock(TransitionController.class); - BLASTSyncEngine sync = new BLASTSyncEngine(mWm); - Transition transition = new Transition( - TRANSIT_OLD_TASK_OPEN, 0 /* flags */, controller, sync); + final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN); final Task openTask = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent); @@ -214,8 +229,9 @@ public class TransitionTests extends WindowTestsBase { opening.mVisibleRequested = true; closing.mVisibleRequested = false; - TransitionInfo info = Transition.calculateTransitionInfo( - 0, transition.mParticipants, transition.mChanges); + ArraySet<WindowContainer> targets = Transition.calculateTargets( + transition.mParticipants, transition.mChanges); + TransitionInfo info = Transition.calculateTransitionInfo(0, targets, transition.mChanges); assertEquals(2, info.getChanges().size()); // There was an existence change on open, so it should be OPEN rather than SHOW assertEquals(TRANSIT_OPEN, @@ -224,4 +240,39 @@ public class TransitionTests extends WindowTestsBase { assertEquals(TRANSIT_HIDE, info.getChange(closeTask.mRemoteToken.toWindowContainerToken()).getMode()); } + + @Test + public void testCreateInfo_ordering() { + final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN); + // pick some number with a high enough chance of being out-of-order when added to set. + final int taskCount = 6; + + final Task[] tasks = new Task[taskCount]; + for (int i = 0; i < taskCount; ++i) { + // Each add goes on top, so at the end of this, task[9] should be on top + tasks[i] = createTaskStackOnDisplay(WINDOWING_MODE_FREEFORM, + ACTIVITY_TYPE_STANDARD, mDisplayContent); + final ActivityRecord act = createActivityRecord(tasks[i]); + // alternate so that the transition doesn't get promoted to the display area + act.mVisibleRequested = (i % 2) == 0; // starts invisible + } + + // doesn't matter which order collected since participants is a set + for (int i = 0; i < taskCount; ++i) { + transition.collectExistenceChange(tasks[i]); + final ActivityRecord act = tasks[i].getTopMostActivity(); + transition.collect(act); + tasks[i].getTopMostActivity().mVisibleRequested = (i % 2) != 0; + } + + ArraySet<WindowContainer> targets = Transition.calculateTargets( + transition.mParticipants, transition.mChanges); + TransitionInfo info = Transition.calculateTransitionInfo(0, targets, transition.mChanges); + assertEquals(taskCount, info.getChanges().size()); + // verify order is top-to-bottem + for (int i = 0; i < taskCount; ++i) { + assertEquals(tasks[taskCount - i - 1].mRemoteToken.toWindowContainerToken(), + info.getChanges().get(i).getContainer()); + } + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java index 5afcedb10dd6..3057558a6e98 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java @@ -27,10 +27,13 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; import android.Manifest; import android.app.IApplicationThread; @@ -327,6 +330,45 @@ public class WindowProcessControllerTests extends WindowTestsBase { return new ActivityBuilder(mAtm).setCreateTask(true).setUseProcess(wpc).build(); } + @Test + public void testTopActivityDisplayAreaMatchesTopMostActivity_noActivities() { + assertNull(mWpc.getTopActivityDisplayArea()); + } + + @Test + public void testTopActivityDisplayAreaMatchesTopMostActivity_singleActivity() { + final ActivityRecord activityRecord = new ActivityBuilder(mSupervisor.mService).build(); + final TaskDisplayArea expectedDisplayArea = mock(TaskDisplayArea.class); + + when(activityRecord.getDisplayArea()) + .thenReturn(expectedDisplayArea); + + mWpc.addActivityIfNeeded(activityRecord); + + assertEquals(expectedDisplayArea, mWpc.getTopActivityDisplayArea()); + } + + /** + * Test that top most activity respects z-order. + */ + @Test + public void testTopActivityDisplayAreaMatchesTopMostActivity_multipleActivities() { + final ActivityRecord bottomRecord = new ActivityBuilder(mSupervisor.mService).build(); + final TaskDisplayArea bottomDisplayArea = mock(TaskDisplayArea.class); + final ActivityRecord topRecord = new ActivityBuilder(mSupervisor.mService).build(); + final TaskDisplayArea topDisplayArea = mock(TaskDisplayArea.class); + + when(bottomRecord.getDisplayArea()).thenReturn(bottomDisplayArea); + when(topRecord.getDisplayArea()).thenReturn(topDisplayArea); + doReturn(-1).when(bottomRecord).compareTo(topRecord); + doReturn(1).when(topRecord).compareTo(bottomRecord); + + mWpc.addActivityIfNeeded(topRecord); + mWpc.addActivityIfNeeded(bottomRecord); + + assertEquals(topDisplayArea, mWpc.getTopActivityDisplayArea()); + } + private TestDisplayContent createTestDisplayContentInContainer() { return new TestDisplayContent.Builder(mAtm, 1000, 1500).build(); } 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 1d498bd3253b..227eba2a041b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -648,6 +648,8 @@ public class WindowStateTests extends WindowTestsBase { win1.mSurfaceControl = mock(SurfaceControl.class); win1.mAttrs.surfaceInsets.set(1, 2, 3, 4); win1.getFrame().offsetTo(WINDOW_OFFSET, 0); + // Simulate layout + win1.mRelayoutCalled = true; win1.updateSurfacePosition(t); win1.getTransformationMatrix(values, matrix); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 83053813116b..6c046bda1444 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -40,6 +40,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; @@ -80,6 +82,7 @@ import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.View; import android.view.WindowManager; +import android.view.WindowManager.DisplayImePolicy; import android.window.ITaskOrganizer; import com.android.internal.util.ArrayUtils; @@ -174,7 +177,7 @@ class WindowTestsBase extends SystemServiceTestsBase { private void createTestDisplay(UseTestDisplay annotation) { beforeCreateTestDisplay(); - mDisplayContent = createNewDisplay(true /* supportIme */); + mDisplayContent = createNewDisplayWithImeSupport(DISPLAY_IME_POLICY_LOCAL); final boolean addAll = annotation.addAllCommonWindows(); final @CommonTypes int[] requestedWindows = annotation.addWindows(); @@ -482,26 +485,26 @@ class WindowTestsBase extends SystemServiceTestsBase { /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */ DisplayContent createNewDisplay() { - return createNewDisplay(true /* supportIme */); + return createNewDisplayWithImeSupport(DISPLAY_IME_POLICY_LOCAL); } /** Creates a {@link DisplayContent} and adds it to the system. */ - private DisplayContent createNewDisplay(boolean supportIme) { - return createNewDisplay(mDisplayInfo, supportIme); + private DisplayContent createNewDisplayWithImeSupport(@DisplayImePolicy int imePolicy) { + return createNewDisplay(mDisplayInfo, imePolicy); } /** Creates a {@link DisplayContent} that supports IME and adds it to the system. */ DisplayContent createNewDisplay(DisplayInfo info) { - return createNewDisplay(info, true /* supportIme */); + return createNewDisplay(info, DISPLAY_IME_POLICY_LOCAL); } /** Creates a {@link DisplayContent} and adds it to the system. */ - private DisplayContent createNewDisplay(DisplayInfo info, boolean supportIme) { + private DisplayContent createNewDisplay(DisplayInfo info, @DisplayImePolicy int imePolicy) { final DisplayContent display = new TestDisplayContent.Builder(mAtm, info).build(); final DisplayContent dc = display.mDisplayContent; // this display can show IME. - dc.mWmService.mDisplayWindowSettings.setShouldShowImeLocked(dc, supportIme); + dc.mWmService.mDisplayWindowSettings.setDisplayImePolicy(dc, imePolicy); return dc; } @@ -516,7 +519,7 @@ class WindowTestsBase extends SystemServiceTestsBase { DisplayInfo displayInfo = new DisplayInfo(); displayInfo.copyFrom(mDisplayInfo); displayInfo.state = displayState; - return createNewDisplay(displayInfo, true /* supportIme */); + return createNewDisplay(displayInfo, DISPLAY_IME_POLICY_LOCAL); } /** Creates a {@link TestWindowState} */ @@ -532,7 +535,7 @@ class WindowTestsBase extends SystemServiceTestsBase { displayInfo.copyFrom(mDisplayInfo); displayInfo.type = Display.TYPE_VIRTUAL; displayInfo.ownerUid = SYSTEM_UID; - return createNewDisplay(displayInfo, false /* supportIme */); + return createNewDisplay(displayInfo, DISPLAY_IME_POLICY_FALLBACK_DISPLAY); } IDisplayWindowInsetsController createDisplayWindowInsetsController() { diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 5024ae27ee49..835ecaa8c90d 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -361,7 +361,13 @@ public final class PhoneAccount implements Parcelable { */ public static final int CAPABILITY_ADHOC_CONFERENCE_CALLING = 0x4000; - /* NEXT CAPABILITY: 0x8000 */ + /** + * Flag indicating whether this {@link PhoneAccount} is capable of supporting the call composer + * functionality for enriched calls. + */ + public static final int CAPABILITY_CALL_COMPOSER = 0x8000; + + /* NEXT CAPABILITY: 0x10000 */ /** * URI scheme for telephone number URIs. @@ -1088,6 +1094,9 @@ public final class PhoneAccount implements Parcelable { if (hasCapabilities(CAPABILITY_ADHOC_CONFERENCE_CALLING)) { sb.append("AdhocConf"); } + if (hasCapabilities(CAPABILITY_CALL_COMPOSER)) { + sb.append("CallComposer "); + } return sb.toString(); } diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index ada069666547..8d7742b7510b 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -76,39 +76,46 @@ public class RcsUceAdapter { * @hide */ public static final int ERROR_GENERIC_FAILURE = 1; + /** * The carrier network does not have UCE support enabled for this subscriber. * @hide */ public static final int ERROR_NOT_ENABLED = 2; + /** * The data network that the device is connected to does not support UCE currently (e.g. it is * 1x only currently). * @hide */ public static final int ERROR_NOT_AVAILABLE = 3; + /** * The network has responded with SIP 403 error and a reason "User not registered." * @hide */ public static final int ERROR_NOT_REGISTERED = 4; + /** * The network has responded to this request with a SIP 403 error and reason "not authorized for * presence" for this subscriber. * @hide */ public static final int ERROR_NOT_AUTHORIZED = 5; + /** * The network has responded to this request with a SIP 403 error and no reason. * @hide */ public static final int ERROR_FORBIDDEN = 6; + /** * The contact URI requested is not provisioned for VoLTE or it is not known as an IMS * subscriber to the carrier network. * @hide */ public static final int ERROR_NOT_FOUND = 7; + /** * The capabilities request contained too many URIs for the carrier network to handle. Retry * with a lower number of contact numbers. The number varies per carrier. @@ -116,22 +123,32 @@ public class RcsUceAdapter { */ // TODO: Try to integrate this into the API so that the service will split based on carrier. public static final int ERROR_REQUEST_TOO_LARGE = 8; + /** * The network did not respond to the capabilities request before the request timed out. * @hide */ public static final int ERROR_REQUEST_TIMEOUT = 10; + /** * The request failed due to the service having insufficient memory. * @hide */ public static final int ERROR_INSUFFICIENT_MEMORY = 11; + /** * The network was lost while trying to complete the request. * @hide */ public static final int ERROR_LOST_NETWORK = 12; + /** + * The network is temporarily unavailable or busy. Retries should only be done after the retry + * time returned in {@link CapabilitiesCallback#onError} has elapsed. + * @hide + */ + public static final int ERROR_SERVER_UNAVAILABLE = 13; + /**@hide*/ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "ERROR_", value = { @@ -145,7 +162,8 @@ public class RcsUceAdapter { ERROR_REQUEST_TOO_LARGE, ERROR_REQUEST_TIMEOUT, ERROR_INSUFFICIENT_MEMORY, - ERROR_LOST_NETWORK + ERROR_LOST_NETWORK, + ERROR_SERVER_UNAVAILABLE }) public @interface ErrorCode {} @@ -369,8 +387,10 @@ public class RcsUceAdapter { * The pending request has resulted in an error and may need to be retried, depending on the * error code. * @param errorCode The reason for the framework being unable to process the request. + * @param retryAfterMilliseconds The time in milliseconds the requesting application should + * wait before retrying, if non-zero. */ - void onError(@ErrorCode int errorCode); + void onError(@ErrorCode int errorCode, long retryAfterMilliseconds); } private final Context mContext; @@ -451,10 +471,10 @@ public class RcsUceAdapter { } } @Override - public void onError(int errorCode) { + public void onError(int errorCode, long retryAfterMilliseconds) { final long callingIdentity = Binder.clearCallingIdentity(); try { - executor.execute(() -> c.onError(errorCode)); + executor.execute(() -> c.onError(errorCode, retryAfterMilliseconds)); } finally { restoreCallingIdentity(callingIdentity); } @@ -535,10 +555,10 @@ public class RcsUceAdapter { } } @Override - public void onError(int errorCode) { + public void onError(int errorCode, long retryAfterMilliseconds) { final long callingIdentity = Binder.clearCallingIdentity(); try { - executor.execute(() -> c.onError(errorCode)); + executor.execute(() -> c.onError(errorCode, retryAfterMilliseconds)); } finally { restoreCallingIdentity(callingIdentity); } diff --git a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl index 0bd3e5ed354e..0f627b92a24c 100644 --- a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl @@ -26,5 +26,5 @@ import android.telephony.ims.RcsContactUceCapability; oneway interface IRcsUceControllerCallback { void onCapabilitiesReceived(in List<RcsContactUceCapability> contactCapabilities); void onComplete(); - void onError(int errorCode); + void onError(int errorCode, long retryAfterMilliseconds); } diff --git a/tests/BootImageProfileTest/TEST_MAPPING b/tests/BootImageProfileTest/TEST_MAPPING deleted file mode 100644 index 1b569f9455bf..000000000000 --- a/tests/BootImageProfileTest/TEST_MAPPING +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presubmit": [ - { - "name": "BootImageProfileTest" - } - ] -} diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt index d476e73837f4..a20f96d17278 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt @@ -16,7 +16,6 @@ package com.android.server.wm.flicker.close -import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry @@ -52,7 +51,6 @@ import org.junit.runners.Parameterized * Test app closes by pressing back button * To run this test: `atest FlickerTests:CloseAppBackButtonTest` */ -@Presubmit @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt index e3789fea5cba..4bbb38c4d71a 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt @@ -16,7 +16,6 @@ package com.android.server.wm.flicker.close -import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import androidx.test.platform.app.InstrumentationRegistry @@ -52,7 +51,6 @@ import org.junit.runners.Parameterized * Test app closes by pressing home button. * To run this test: `atest FlickerTests:CloseAppHomeButtonTest` */ -@Presubmit @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index 52718bec9148..3d8deb5cfc8d 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -34,7 +34,6 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.cts.install.lib.Install; import com.android.cts.install.lib.InstallUtils; -import com.android.cts.install.lib.LocalIntentSender; import com.android.cts.install.lib.TestApp; import com.android.cts.install.lib.Uninstall; import com.android.cts.rollback.lib.Rollback; @@ -258,10 +257,6 @@ public class StagedRollbackTest { .getPackageManager().getPackageInstaller(); pi.abandonSession(sessionId); - // Remove the first intent sender result, so that the next staged install session does not - // erroneously think that it has itself been abandoned. - // TODO(b/136260017): Restructure LocalIntentSender to negate the need for this step. - LocalIntentSender.getIntentSenderResult(); Install.single(TestApp.A2).setStaged().setEnableRollback().commit(); } diff --git a/tests/net/common/java/android/net/OemNetworkPreferencesTest.java b/tests/net/common/java/android/net/OemNetworkPreferencesTest.java index b77ed6ab5a29..c9161b6d6441 100644 --- a/tests/net/common/java/android/net/OemNetworkPreferencesTest.java +++ b/tests/net/common/java/android/net/OemNetworkPreferencesTest.java @@ -22,11 +22,14 @@ import static com.android.testutils.ParcelUtils.assertParcelSane; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import android.os.Build; import android.util.SparseArray; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,6 +37,7 @@ import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; +@IgnoreUpTo(Build.VERSION_CODES.R) @RunWith(AndroidJUnit4.class) @SmallTest public class OemNetworkPreferencesTest { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 2758f6156c16..ba87dc50e246 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -18,6 +18,8 @@ package com.android.server; import static android.Manifest.permission.CHANGE_NETWORK_STATE; import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; +import static android.content.Intent.ACTION_USER_ADDED; +import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; @@ -1056,7 +1058,9 @@ public class ConnectivityServiceTest { public void setUids(Set<UidRange> uids) { mNetworkCapabilities.setUids(uids); - updateCapabilitiesInternal(null /* defaultNetwork */, true); + if (mAgentRegistered) { + mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true); + } } public void setVpnType(int vpnType) { @@ -1082,11 +1086,15 @@ public class ConnectivityServiceTest { throws Exception { if (mAgentRegistered) throw new IllegalStateException("already registered"); setUids(uids); - mConfig.isMetered = isAlwaysMetered; + if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED); mInterface = VPN_IFNAME; mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp, mNetworkCapabilities); mMockNetworkAgent.waitForIdle(TIMEOUT_MS); + verify(mNetworkManagementService, times(1)) + .addVpnUidRanges(eq(mMockVpn.getNetId()), eq(uids.toArray(new UidRange[0]))); + verify(mNetworkManagementService, never()) + .removeVpnUidRanges(eq(mMockVpn.getNetId()), any()); mAgentRegistered = true; mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); mNetworkAgent = mMockNetworkAgent.getNetworkAgent(); @@ -1141,28 +1149,6 @@ public class ConnectivityServiceTest { mMockNetworkAgent.sendLinkProperties(lp); } - private NetworkCapabilities updateCapabilitiesInternal(Network defaultNetwork, - boolean sendToConnectivityService) { - if (!mAgentRegistered) return null; - super.updateCapabilities(defaultNetwork); - // Because super.updateCapabilities will update the capabilities of the agent but - // not the mock agent, the mock agent needs to know about them. - copyCapabilitiesToNetworkAgent(sendToConnectivityService); - return new NetworkCapabilities(mNetworkCapabilities); - } - - private void copyCapabilitiesToNetworkAgent(boolean sendToConnectivityService) { - if (null != mMockNetworkAgent) { - mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, - sendToConnectivityService); - } - } - - @Override - public NetworkCapabilities updateCapabilities(Network defaultNetwork) { - return updateCapabilitiesInternal(defaultNetwork, false); - } - public void disconnect() { if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect(); mAgentRegistered = false; @@ -4944,8 +4930,6 @@ public class ConnectivityServiceTest { final Network[] cellAndVpn = new Network[] { mCellNetworkAgent.getNetwork(), mMockVpn.getNetwork()}; - Network[] cellAndWifi = new Network[] { - mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()}; // A VPN with default (null) underlying networks sets the underlying network's interfaces... expectForceUpdateIfaces(cellAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, @@ -4955,10 +4939,13 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); mWiFiNetworkAgent.sendLinkProperties(wifiLp); + final Network[] onlyNull = new Network[]{null}; final Network[] wifiAndVpn = new Network[] { mWiFiNetworkAgent.getNetwork(), mMockVpn.getNetwork()}; - cellAndWifi = new Network[] { + final Network[] cellAndWifi = new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork()}; + final Network[] cellNullAndWifi = new Network[] { + mCellNetworkAgent.getNetwork(), null, mWiFiNetworkAgent.getNetwork()}; waitForIdle(); assertEquals(wifiLp, mService.getActiveLinkProperties()); @@ -4984,6 +4971,13 @@ public class ConnectivityServiceTest { new String[]{MOBILE_IFNAME, WIFI_IFNAME}); reset(mStatsService); + // Null underlying networks are ignored. + mService.setUnderlyingNetworksForVpn(cellNullAndWifi); + waitForIdle(); + expectForceUpdateIfaces(wifiAndVpn, MOBILE_IFNAME, Process.myUid(), VPN_IFNAME, + new String[]{MOBILE_IFNAME, WIFI_IFNAME}); + reset(mStatsService); + // If an underlying network disconnects, that interface should no longer be underlying. // This doesn't actually work because disconnectAndDestroyNetwork only notifies // NetworkStatsService before the underlying network is actually removed. So the underlying @@ -5018,6 +5012,7 @@ public class ConnectivityServiceTest { argThat(vpnInfos -> vpnInfos[0].underlyingIfaces.length == 1 && WIFI_IFNAME.equals(vpnInfos[0].underlyingIfaces[0]))); mEthernetNetworkAgent.disconnect(); + waitForIdle(); reset(mStatsService); // When a VPN declares no underlying networks (i.e., no connectivity), getAllVpnInfo @@ -5030,6 +5025,25 @@ public class ConnectivityServiceTest { waitForIdle(); expectForceUpdateIfaces(wifiAndVpn, null); reset(mStatsService); + + // Specifying only a null underlying network is the same as no networks. + mService.setUnderlyingNetworksForVpn(onlyNull); + waitForIdle(); + expectForceUpdateIfaces(wifiAndVpn, null); + reset(mStatsService); + + // Specifying networks that are all disconnected is the same as specifying no networks. + mService.setUnderlyingNetworksForVpn(onlyCell); + waitForIdle(); + expectForceUpdateIfaces(wifiAndVpn, null); + reset(mStatsService); + + // Passing in null again means follow the default network again. + mService.setUnderlyingNetworksForVpn(null); + waitForIdle(); + expectForceUpdateIfaces(wifiAndVpn, WIFI_IFNAME, Process.myUid(), VPN_IFNAME, + new String[]{WIFI_IFNAME}); + reset(mStatsService); } @Test @@ -5471,6 +5485,7 @@ public class ConnectivityServiceTest { final Set<UidRange> ranges = uidRangesForUid(uid); mMockVpn.registerAgent(ranges); + mService.setUnderlyingNetworksForVpn(new Network[0]); // VPN networks do not satisfy the default request and are automatically validated // by NetworkMonitor @@ -5479,19 +5494,12 @@ public class ConnectivityServiceTest { mMockVpn.getAgent().setNetworkValid(false /* isStrictMode */); mMockVpn.connect(false); - mService.setUnderlyingNetworksForVpn(new Network[0]); - genericNetworkCallback.expectAvailableCallbacksUnvalidated(mMockVpn); + genericNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); genericNotVpnNetworkCallback.assertNoCallback(); wifiNetworkCallback.assertNoCallback(); - vpnNetworkCallback.expectAvailableCallbacksUnvalidated(mMockVpn); - defaultCallback.expectAvailableCallbacksUnvalidated(mMockVpn); - assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - - genericNetworkCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); - genericNotVpnNetworkCallback.assertNoCallback(); - vpnNetworkCallback.expectCapabilitiesThat(mMockVpn, nc -> null == nc.getUids()); - defaultCallback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, mMockVpn); + vpnNetworkCallback.expectAvailableThenValidatedCallbacks(mMockVpn); + defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); ranges.clear(); @@ -5884,6 +5892,75 @@ public class ConnectivityServiceTest { } @Test + public void testVpnRestrictedUsers() throws Exception { + // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities. + mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS, + PERMISSION_GRANTED); + + final NetworkRequest request = new NetworkRequest.Builder() + .removeCapability(NET_CAPABILITY_NOT_VPN) + .build(); + final TestNetworkCallback callback = new TestNetworkCallback(); + mCm.registerNetworkCallback(request, callback); + + // Bring up a VPN + mMockVpn.establishForMyUid(); + callback.expectAvailableThenValidatedCallbacks(mMockVpn); + callback.assertNoCallback(); + + final int uid = Process.myUid(); + NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork()); + assertNotNull("nc=" + nc, nc.getUids()); + assertEquals(nc.getUids(), uidRangesForUid(uid)); + + // Set an underlying network and expect to see the VPN transports change. + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(true); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + callback.expectCapabilitiesThat(mMockVpn, (caps) + -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_WIFI)); + callback.expectCapabilitiesThat(mWiFiNetworkAgent, (caps) + -> caps.hasCapability(NET_CAPABILITY_VALIDATED)); + + // Create a fake restricted profile whose parent is our user ID. + final int userId = UserHandle.getUserId(uid); + final int restrictedUserId = userId + 1; + final UserInfo info = new UserInfo(restrictedUserId, "user", UserInfo.FLAG_RESTRICTED); + info.restrictedProfileParentId = userId; + assertTrue(info.isRestricted()); + when(mUserManager.getUserInfo(restrictedUserId)).thenReturn(info); + final Intent addedIntent = new Intent(ACTION_USER_ADDED); + addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId); + + // Send a USER_ADDED broadcast for it. + // The BroadcastReceiver for this broadcast checks that is being run on the handler thread. + final Handler handler = new Handler(mCsHandlerThread.getLooper()); + handler.post(() -> mServiceContext.sendBroadcast(addedIntent)); + + // Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added + // restricted user. + callback.expectCapabilitiesThat(mMockVpn, (caps) + -> caps.getUids().size() == 2 + && caps.getUids().contains(new UidRange(uid, uid)) + && caps.getUids().contains(UidRange.createForUser(restrictedUserId)) + && caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_WIFI)); + + // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user. + final Intent removedIntent = new Intent(ACTION_USER_REMOVED); + removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId); + handler.post(() -> mServiceContext.sendBroadcast(removedIntent)); + + // Expect that the VPN gains the UID range for the restricted user. + callback.expectCapabilitiesThat(mMockVpn, (caps) + -> caps.getUids().size() == 1 + && caps.getUids().contains(new UidRange(uid, uid)) + && caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_WIFI)); + } + + @Test public void testIsActiveNetworkMeteredOverWifi() throws Exception { // Returns true by default when no network is available. assertTrue(mCm.isActiveNetworkMetered()); @@ -6829,8 +6906,8 @@ public class ConnectivityServiceTest { final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); mMockVpn.establish(lp, VPN_UID, vpnRange); - // Connected VPN should have interface rules set up. There are two expected invocations, - // one during VPN uid update, one during VPN LinkProperties update + // A connected VPN should have interface rules set up. There are two expected invocations, + // one during the VPN initial connection, one during the VPN LinkProperties update. ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class); verify(mMockNetd, times(2)).firewallAddUidInterfaceRules(eq("tun0"), uidCaptor.capture()); assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID); @@ -7345,20 +7422,14 @@ public class ConnectivityServiceTest { setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); - // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be - // active - final VpnInfo info = new VpnInfo(); - info.ownerUid = Process.myUid(); - info.vpnIface = VPN_IFNAME; - mMockVpn.setVpnInfo(info); - mMockVpn.establishForMyUid(); - waitForIdle(); + // Wait for networks to connect and broadcasts to be sent before removing permissions. + waitForIdle(); mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); - assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {network})); + waitForIdle(); assertTrue( "Active VPN permission not applied", mService.checkConnectivityDiagnosticsPermissions( @@ -7366,6 +7437,7 @@ public class ConnectivityServiceTest { mContext.getOpPackageName())); assertTrue(mService.setUnderlyingNetworksForVpn(null)); + waitForIdle(); assertFalse( "VPN shouldn't receive callback on non-underlying network", mService.checkConnectivityDiagnosticsPermissions( diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 1dcc07c6db81..d0db55f2bb13 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -41,6 +41,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; @@ -86,10 +87,10 @@ import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.ConditionVariable; import android.os.INetworkManagementService; -import android.os.Looper; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; +import android.os.test.TestLooper; import android.provider.Settings; import android.security.Credentials; import android.security.KeyStore; @@ -100,6 +101,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; +import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; import com.android.server.IpSecService; @@ -223,6 +225,8 @@ public class VpnTest { .thenReturn(mNotificationManager); when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE))) .thenReturn(mConnectivityManager); + when(mContext.getSystemServiceName(eq(ConnectivityManager.class))) + .thenReturn(Context.CONNECTIVITY_SERVICE); when(mContext.getSystemService(eq(Context.IPSEC_SERVICE))).thenReturn(mIpSecManager); when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)) .thenReturn(Resources.getSystem().getString( @@ -589,7 +593,7 @@ public class VpnTest { } @Test - public void testNotificationShownForAlwaysOnApp() { + public void testNotificationShownForAlwaysOnApp() throws Exception { final UserHandle userHandle = UserHandle.of(primaryUser.id); final Vpn vpn = createVpn(primaryUser.id); setMockedUsers(primaryUser); @@ -619,7 +623,6 @@ public class VpnTest { @Test public void testCapabilities() { - final Vpn vpn = createVpn(primaryUser.id); setMockedUsers(primaryUser); final Network mobile = new Network(1); @@ -1037,7 +1040,7 @@ public class VpnTest { when(exception.getErrorType()) .thenReturn(IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED); - final Vpn vpn = startLegacyVpn(mVpnProfile); + final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), (mVpnProfile)); final NetworkCallback cb = triggerOnAvailableAndGetCallback(); // Wait for createIkeSession() to be called before proceeding in order to ensure consistent @@ -1048,20 +1051,20 @@ public class VpnTest { ikeCb.onClosedExceptionally(exception); verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb)); - assertEquals(DetailedState.FAILED, vpn.getNetworkInfo().getDetailedState()); + assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state); } @Test public void testStartPlatformVpnIllegalArgumentExceptionInSetup() throws Exception { when(mIkev2SessionCreator.createIkeSession(any(), any(), any(), any(), any(), any())) .thenThrow(new IllegalArgumentException()); - final Vpn vpn = startLegacyVpn(mVpnProfile); + final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); final NetworkCallback cb = triggerOnAvailableAndGetCallback(); // Wait for createIkeSession() to be called before proceeding in order to ensure consistent // state verify(mConnectivityManager, timeout(TEST_TIMEOUT_MS)).unregisterNetworkCallback(eq(cb)); - assertEquals(DetailedState.FAILED, vpn.getNetworkInfo().getDetailedState()); + assertEquals(LegacyVpnInfo.STATE_FAILED, vpn.getLegacyVpnInfo().state); } private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) { @@ -1100,8 +1103,7 @@ public class VpnTest { // a subsequent CL. } - public Vpn startLegacyVpn(final VpnProfile vpnProfile) throws Exception { - final Vpn vpn = createVpn(primaryUser.id); + private Vpn startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile) throws Exception { setMockedUsers(primaryUser); // Dummy egress interface @@ -1118,7 +1120,7 @@ public class VpnTest { @Test public void testStartPlatformVpn() throws Exception { - startLegacyVpn(mVpnProfile); + startLegacyVpn(createVpn(primaryUser.id), mVpnProfile); // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in // a subsequent patch. } @@ -1153,7 +1155,7 @@ public class VpnTest { legacyRunnerReady.open(); return new Network(102); }); - final Vpn vpn = startLegacyVpn(profile); + final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile); final TestDeps deps = (TestDeps) vpn.mDeps; try { // udppsk and 1701 are the values for TYPE_L2TP_IPSEC_PSK @@ -1287,8 +1289,13 @@ public class VpnTest { doReturn(UserHandle.of(userId)).when(asUserContext).getUser(); when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt())) .thenReturn(asUserContext); - return new Vpn(Looper.myLooper(), mContext, new TestDeps(), mNetService, + final TestLooper testLooper = new TestLooper(); + final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService, userId, mKeyStore, mSystemServices, mIkev2SessionCreator); + verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat( + provider -> provider.getName().contains("VpnNetworkProvider") + )); + return vpn; } private static void assertBlocked(Vpn vpn, int... uids) { |